From ecb8b9f9f768a3245e8ae723005d5c408bf2067a Mon Sep 17 00:00:00 2001 From: Jack Huey Date: Wed, 27 May 2020 01:05:09 -0400 Subject: [PATCH] Update Chalk --- Cargo.lock | 49 ++++- src/librustc_middle/Cargo.toml | 2 +- src/librustc_middle/traits/chalk.rs | 2 + .../traits/chalk_fulfill.rs | 15 +- src/librustc_traits/Cargo.toml | 4 +- src/librustc_traits/chalk/db.rs | 180 ++++++++++++++---- src/librustc_traits/chalk/lowering.rs | 42 ++-- src/librustc_traits/chalk/mod.rs | 1 + src/test/ui/chalkify/closure.rs | 39 ++++ src/test/ui/chalkify/closure.stderr | 18 ++ src/test/ui/chalkify/impl_wf.rs | 7 +- src/test/ui/chalkify/impl_wf.stderr | 15 +- src/test/ui/chalkify/inherent_impl.rs | 17 +- .../recursive_where_clause_on_type.rs | 11 +- .../recursive_where_clause_on_type.stderr | 16 +- 15 files changed, 311 insertions(+), 107 deletions(-) create mode 100644 src/test/ui/chalkify/closure.rs create mode 100644 src/test/ui/chalkify/closure.stderr diff --git a/Cargo.lock b/Cargo.lock index b54566e7176b0..e0d092ec76a78 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -434,9 +434,9 @@ dependencies = [ [[package]] name = "chalk-derive" -version = "0.11.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9bd01eab87277d973183a1d2e56bace1c11f8242c52c20636fb7dddf343ac9" +checksum = "d463e01905d607e181de72e8608721d3269f29176c9a14ce037011316ae7131d" dependencies = [ "proc-macro2 1.0.3", "quote 1.0.2", @@ -446,20 +446,21 @@ dependencies = [ [[package]] name = "chalk-engine" -version = "0.11.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c7a637c3d17ed555aef16e16952a5d1e127bd55178cc30be22afeb92da90c7d" +checksum = "efaf428f5398d36284f79690cf988762b7c091249f50a6c11db613a46c057000" dependencies = [ "chalk-derive", "chalk-ir", "rustc-hash", + "tracing", ] [[package]] name = "chalk-ir" -version = "0.11.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "595e5735ded16c3f3dc348f7b15bbb2521a0080b1863cac38ad5271589944670" +checksum = "fd3fdc1e9f68498ffe80f4a23b0b95f1ca6fb21d5a4c9b0c085fab3ca712bdbe" dependencies = [ "chalk-derive", "lazy_static", @@ -467,9 +468,9 @@ dependencies = [ [[package]] name = "chalk-solve" -version = "0.11.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d9d938139db425867a30cc0cfec0269406d8238d0571d829041eaa7a8455d11" +checksum = "5b9fd4102807b7ebe8fb034fa0f488c5656e1966d3261b558b81a08d519cdb29" dependencies = [ "chalk-derive", "chalk-engine", @@ -478,6 +479,7 @@ dependencies = [ "itertools 0.9.0", "petgraph", "rustc-hash", + "tracing", ] [[package]] @@ -5332,6 +5334,37 @@ dependencies = [ "syn 0.15.35", ] +[[package]] +name = "tracing" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a41f40ed0e162c911ac6fcb53ecdc8134c46905fdbbae8c50add462a538b495f" +dependencies = [ + "cfg-if", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99bbad0de3fd923c9c3232ead88510b783e5a4d16a6154adffa3d53308de984c" +dependencies = [ + "proc-macro2 1.0.3", + "quote 1.0.2", + "syn 1.0.11", +] + +[[package]] +name = "tracing-core" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aa83a9a47081cd522c09c81b31aec2c9273424976f922ad61c053b58350b715" +dependencies = [ + "lazy_static", +] + [[package]] name = "try-lock" version = "0.2.2" diff --git a/src/librustc_middle/Cargo.toml b/src/librustc_middle/Cargo.toml index 21d0b102a4a66..02d82c6793386 100644 --- a/src/librustc_middle/Cargo.toml +++ b/src/librustc_middle/Cargo.toml @@ -30,7 +30,7 @@ rustc_serialize = { path = "../librustc_serialize" } rustc_ast = { path = "../librustc_ast" } rustc_span = { path = "../librustc_span" } byteorder = { version = "1.3" } -chalk-ir = "0.11.0" +chalk-ir = "0.14.0" smallvec = { version = "1.0", features = ["union", "may_dangle"] } measureme = "0.7.1" rustc_session = { path = "../librustc_session" } diff --git a/src/librustc_middle/traits/chalk.rs b/src/librustc_middle/traits/chalk.rs index a49a0045812b0..405af8cb2406c 100644 --- a/src/librustc_middle/traits/chalk.rs +++ b/src/librustc_middle/traits/chalk.rs @@ -10,6 +10,7 @@ use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt}; use rustc_hir::def_id::DefId; +use rustc_target::spec::abi::Abi; use smallvec::SmallVec; @@ -77,6 +78,7 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> { type DefId = DefId; type InternedAdtId = &'tcx AdtDef; type Identifier = (); + type FnAbi = Abi; fn debug_program_clause_implication( pci: &chalk_ir::ProgramClauseImplication, diff --git a/src/librustc_trait_selection/traits/chalk_fulfill.rs b/src/librustc_trait_selection/traits/chalk_fulfill.rs index cbbff82d35f73..2ade489275262 100644 --- a/src/librustc_trait_selection/traits/chalk_fulfill.rs +++ b/src/librustc_trait_selection/traits/chalk_fulfill.rs @@ -7,17 +7,17 @@ use crate::traits::{ ChalkEnvironmentAndGoal, ChalkEnvironmentClause, FulfillmentError, FulfillmentErrorCode, ObligationCause, PredicateObligation, SelectionError, TraitEngine, }; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::FxIndexSet; use rustc_hir::def_id::DefId; use rustc_middle::ty::{self, Ty, TyCtxt}; pub struct FulfillmentContext<'tcx> { - obligations: FxHashSet>, + obligations: FxIndexSet>, } impl FulfillmentContext<'tcx> { crate fn new() -> Self { - FulfillmentContext { obligations: FxHashSet::default() } + FulfillmentContext { obligations: FxIndexSet::default() } } } @@ -79,7 +79,7 @@ fn environment<'tcx>( }; // FIXME(eddyb) isn't the unordered nature of this a hazard? - let mut inputs = FxHashSet::default(); + let mut inputs = FxIndexSet::default(); match node_kind { // In a trait impl, we assume that the header trait ref and all its @@ -140,7 +140,8 @@ fn in_environment( None if obligation.param_env.caller_bounds.is_empty() => ty::List::empty(), // FIXME(chalk): this is hit in ui/where-clauses/where-clause-constraints-are-local-for-trait-impl // and ui/generics/generic-static-methods - _ => bug!("non-empty `ParamEnv` with no def-id"), + //_ => bug!("non-empty `ParamEnv` with no def-id"), + _ => ty::List::empty(), }; ChalkEnvironmentAndGoal { environment, goal: obligation.predicate } @@ -195,7 +196,7 @@ impl TraitEngine<'tcx> for FulfillmentContext<'tcx> { infcx: &InferCtxt<'_, 'tcx>, ) -> Result<(), Vec>> { let mut errors = Vec::new(); - let mut next_round = FxHashSet::default(); + let mut next_round = FxIndexSet::default(); let mut making_progress; loop { @@ -203,7 +204,7 @@ impl TraitEngine<'tcx> for FulfillmentContext<'tcx> { // We iterate over all obligations, and record if we are able // to unambiguously prove at least one obligation. - for obligation in self.obligations.drain() { + for obligation in self.obligations.drain(..) { let goal_in_environment = in_environment(infcx, &obligation); let mut orig_values = OriginalQueryValues::default(); let canonical_goal = diff --git a/src/librustc_traits/Cargo.toml b/src/librustc_traits/Cargo.toml index 8def98a9603d8..079b9b10fd090 100644 --- a/src/librustc_traits/Cargo.toml +++ b/src/librustc_traits/Cargo.toml @@ -16,8 +16,8 @@ rustc_hir = { path = "../librustc_hir" } rustc_index = { path = "../librustc_index" } rustc_ast = { path = "../librustc_ast" } rustc_span = { path = "../librustc_span" } -chalk-ir = "0.11.0" -chalk-solve = "0.11.0" +chalk-ir = "0.14.0" +chalk-solve = "0.14.0" smallvec = { version = "1.0", features = ["union", "may_dangle"] } rustc_infer = { path = "../librustc_infer" } rustc_trait_selection = { path = "../librustc_trait_selection" } diff --git a/src/librustc_traits/chalk/db.rs b/src/librustc_traits/chalk/db.rs index 235497d374098..715e5299a37bd 100644 --- a/src/librustc_traits/chalk/db.rs +++ b/src/librustc_traits/chalk/db.rs @@ -8,7 +8,7 @@ use rustc_middle::traits::ChalkRustInterner as RustInterner; use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef}; -use rustc_middle::ty::{self, AssocItemContainer, AssocKind, Binder, TyCtxt}; +use rustc_middle::ty::{self, AssocItemContainer, AssocKind, TyCtxt}; use rustc_hir::def_id::DefId; @@ -85,14 +85,29 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t .iter() .map(|(wc, _)| wc.subst(self.tcx, &bound_vars)) .filter_map(|wc| LowerInto::>>>::lower_into(wc, &self.interner)).collect(); + let associated_ty_ids: Vec<_> = self + .tcx + .associated_items(def_id) + .in_definition_order() + .filter(|i| i.kind == AssocKind::Type) + .map(|i| chalk_ir::AssocTypeId(i.def_id)) + .collect(); let well_known = if self.tcx.lang_items().sized_trait().map(|t| def_id == t).unwrap_or(false) { - Some(chalk_solve::rust_ir::WellKnownTrait::SizedTrait) + Some(chalk_solve::rust_ir::WellKnownTrait::Sized) } else if self.tcx.lang_items().copy_trait().map(|t| def_id == t).unwrap_or(false) { - Some(chalk_solve::rust_ir::WellKnownTrait::CopyTrait) + Some(chalk_solve::rust_ir::WellKnownTrait::Copy) } else if self.tcx.lang_items().clone_trait().map(|t| def_id == t).unwrap_or(false) { - Some(chalk_solve::rust_ir::WellKnownTrait::CloneTrait) + Some(chalk_solve::rust_ir::WellKnownTrait::Clone) + } else if self.tcx.lang_items().drop_trait().map(|t| def_id == t).unwrap_or(false) { + Some(chalk_solve::rust_ir::WellKnownTrait::Drop) + } else if self.tcx.lang_items().fn_trait().map(|t| def_id == t).unwrap_or(false) { + Some(chalk_solve::rust_ir::WellKnownTrait::Fn) + } else if self.tcx.lang_items().fn_once_trait().map(|t| def_id == t).unwrap_or(false) { + Some(chalk_solve::rust_ir::WellKnownTrait::FnOnce) + } else if self.tcx.lang_items().fn_mut_trait().map(|t| def_id == t).unwrap_or(false) { + Some(chalk_solve::rust_ir::WellKnownTrait::FnMut) } else { None }; @@ -110,7 +125,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t non_enumerable: true, coinductive: false, }, - associated_ty_ids: vec![], + associated_ty_ids, well_known, }) } @@ -156,6 +171,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t flags: chalk_solve::rust_ir::AdtFlags { upstream: !adt_def.did.is_local(), fundamental: adt_def.is_fundamental(), + phantom_data: adt_def.is_phantom_data(), }, }); return struct_datum; @@ -176,28 +192,32 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t .filter_map(|wc| LowerInto::>>>::lower_into(wc, &self.interner)).collect(); let sig = self.tcx.fn_sig(def_id); - // FIXME(chalk): collect into an intermediate SmallVec here since - // we need `TypeFoldable` for `no_bound_vars` - let argument_types: Binder> = - sig.map_bound(|i| i.inputs().iter().copied().collect()); - let argument_types = argument_types - .no_bound_vars() - .expect("FIXME(chalk): late-bound fn parameters not supported in chalk") + let inputs_and_output = sig.inputs_and_output(); + let (inputs_and_output, iobinders, _) = crate::chalk::lowering::collect_bound_vars( + &self.interner, + self.tcx, + &inputs_and_output, + ); + + let argument_types = inputs_and_output[..inputs_and_output.len() - 1] .iter() .map(|t| t.subst(self.tcx, &bound_vars).lower_into(&self.interner)) .collect(); - let return_type = sig - .output() - .no_bound_vars() - .expect("FIXME(chalk): late-bound fn parameters not supported in chalk") + let return_type = inputs_and_output[inputs_and_output.len() - 1] .subst(self.tcx, &bound_vars) .lower_into(&self.interner); - let bound = - chalk_solve::rust_ir::FnDefDatumBound { argument_types, where_clauses, return_type }; + let bound = chalk_solve::rust_ir::FnDefDatumBound { + inputs_and_output: chalk_ir::Binders::new( + iobinders, + chalk_solve::rust_ir::FnDefInputsAndOutputDatum { argument_types, return_type }, + ), + where_clauses, + }; Arc::new(chalk_solve::rust_ir::FnDefDatum { id: fn_def_id, + abi: sig.abi(), binders: chalk_ir::Binders::new(binders, bound), }) } @@ -326,9 +346,16 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t &self, opaque_ty_id: chalk_ir::OpaqueTyId>, ) -> Arc>> { - // FIXME(chalk): actually lower opaque ty + let bound_vars = bound_vars_for_item(self.tcx, opaque_ty_id.0); + let binders = binders_for(&self.interner, bound_vars); + let predicates = self.tcx.predicates_defined_on(opaque_ty_id.0).predicates; + let where_clauses: Vec<_> = predicates + .iter() + .map(|(wc, _)| wc.subst(self.tcx, &bound_vars)) + .filter_map(|wc| LowerInto::>>>::lower_into(wc, &self.interner)).collect(); + let value = chalk_solve::rust_ir::OpaqueTyDatumBound { - bounds: chalk_ir::Binders::new(chalk_ir::VariableKinds::new(&self.interner), vec![]), + bounds: chalk_ir::Binders::new(binders, where_clauses), }; Arc::new(chalk_solve::rust_ir::OpaqueTyDatum { opaque_ty_id, @@ -346,7 +373,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t ) -> Option { use chalk_ir::TyData::*; match well_known { - chalk_solve::rust_ir::WellKnownTrait::SizedTrait => match ty { + chalk_solve::rust_ir::WellKnownTrait::Sized => match ty { Apply(apply) => match apply.name { chalk_ir::TypeName::Adt(chalk_ir::AdtId(adt_def)) => match adt_def.adt_kind() { ty::AdtKind::Struct | ty::AdtKind::Union => None, @@ -364,8 +391,8 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t | InferenceVar(_, _) | BoundVar(_) => None, }, - chalk_solve::rust_ir::WellKnownTrait::CopyTrait - | chalk_solve::rust_ir::WellKnownTrait::CloneTrait => match ty { + chalk_solve::rust_ir::WellKnownTrait::Copy + | chalk_solve::rust_ir::WellKnownTrait::Clone => match ty { Apply(apply) => match apply.name { chalk_ir::TypeName::Adt(chalk_ir::AdtId(adt_def)) => match adt_def.adt_kind() { ty::AdtKind::Struct | ty::AdtKind::Union => None, @@ -383,7 +410,11 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t | InferenceVar(_, _) | BoundVar(_) => None, }, - chalk_solve::rust_ir::WellKnownTrait::DropTrait => None, + chalk_solve::rust_ir::WellKnownTrait::Drop => None, + chalk_solve::rust_ir::WellKnownTrait::Fn => None, + chalk_solve::rust_ir::WellKnownTrait::FnMut => None, + chalk_solve::rust_ir::WellKnownTrait::FnOnce => None, + chalk_solve::rust_ir::WellKnownTrait::Unsize => None, } } @@ -399,17 +430,17 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t well_known_trait: chalk_solve::rust_ir::WellKnownTrait, ) -> Option>> { use chalk_solve::rust_ir::WellKnownTrait::*; - let t = match well_known_trait { - SizedTrait => { - self.tcx.lang_items().sized_trait().map(|t| chalk_ir::TraitId(t)).unwrap() - } - CopyTrait => self.tcx.lang_items().copy_trait().map(|t| chalk_ir::TraitId(t)).unwrap(), - CloneTrait => { - self.tcx.lang_items().clone_trait().map(|t| chalk_ir::TraitId(t)).unwrap() - } - DropTrait => self.tcx.lang_items().drop_trait().map(|t| chalk_ir::TraitId(t)).unwrap(), + let def_id = match well_known_trait { + Sized => self.tcx.lang_items().sized_trait(), + Copy => self.tcx.lang_items().copy_trait(), + Clone => self.tcx.lang_items().clone_trait(), + Drop => self.tcx.lang_items().drop_trait(), + Fn => self.tcx.lang_items().fn_trait(), + FnMut => self.tcx.lang_items().fn_mut_trait(), + FnOnce => self.tcx.lang_items().fn_once_trait(), + Unsize => self.tcx.lang_items().unsize_trait(), }; - Some(t) + def_id.map(|t| chalk_ir::TraitId(t)) } fn is_object_safe(&self, trait_id: chalk_ir::TraitId>) -> bool { @@ -423,6 +454,87 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t // FIXME(chalk): actually get hidden ty self.tcx.mk_ty(ty::Tuple(self.tcx.intern_substs(&[]))).lower_into(&self.interner) } + + fn closure_kind( + &self, + _closure_id: chalk_ir::ClosureId>, + substs: &chalk_ir::Substitution>, + ) -> chalk_solve::rust_ir::ClosureKind { + let kind = &substs.parameters(&self.interner)[substs.len(&self.interner) - 3]; + match kind.assert_ty_ref(&self.interner).data(&self.interner) { + chalk_ir::TyData::Apply(apply) => match apply.name { + chalk_ir::TypeName::Scalar(scalar) => match scalar { + chalk_ir::Scalar::Int(int_ty) => match int_ty { + chalk_ir::IntTy::I8 => chalk_solve::rust_ir::ClosureKind::Fn, + chalk_ir::IntTy::I16 => chalk_solve::rust_ir::ClosureKind::FnMut, + chalk_ir::IntTy::I32 => chalk_solve::rust_ir::ClosureKind::FnOnce, + _ => bug!("bad closure kind"), + }, + _ => bug!("bad closure kind"), + }, + _ => bug!("bad closure kind"), + }, + _ => bug!("bad closure kind"), + } + } + + fn closure_inputs_and_output( + &self, + _closure_id: chalk_ir::ClosureId>, + substs: &chalk_ir::Substitution>, + ) -> chalk_ir::Binders>> + { + let sig = &substs.parameters(&self.interner)[substs.len(&self.interner) - 2]; + match sig.assert_ty_ref(&self.interner).data(&self.interner) { + chalk_ir::TyData::Function(f) => { + let substitution = f.substitution.parameters(&self.interner); + let return_type = + substitution.last().unwrap().assert_ty_ref(&self.interner).clone(); + // Closure arguments are tupled + let argument_tuple = substitution[0].assert_ty_ref(&self.interner); + let argument_types = match argument_tuple.data(&self.interner) { + chalk_ir::TyData::Apply(apply) => match apply.name { + chalk_ir::TypeName::Tuple(_) => apply + .substitution + .iter(&self.interner) + .map(|arg| arg.assert_ty_ref(&self.interner)) + .cloned() + .collect(), + _ => bug!("Expecting closure FnSig args to be tupled."), + }, + _ => bug!("Expecting closure FnSig args to be tupled."), + }; + + chalk_ir::Binders::new( + chalk_ir::VariableKinds::from( + &self.interner, + (0..f.num_binders).map(|_| chalk_ir::VariableKind::Lifetime), + ), + chalk_solve::rust_ir::FnDefInputsAndOutputDatum { argument_types, return_type }, + ) + } + _ => panic!("Invalid sig."), + } + } + + fn closure_upvars( + &self, + _closure_id: chalk_ir::ClosureId>, + substs: &chalk_ir::Substitution>, + ) -> chalk_ir::Binders>> { + let inputs_and_output = self.closure_inputs_and_output(_closure_id, substs); + let tuple = substs.parameters(&self.interner).last().unwrap().assert_ty_ref(&self.interner); + inputs_and_output.map_ref(|_| tuple.clone()) + } + + fn closure_fn_substitution( + &self, + _closure_id: chalk_ir::ClosureId>, + substs: &chalk_ir::Substitution>, + ) -> chalk_ir::Substitution> { + let substitution = &substs.parameters(&self.interner)[0..substs.len(&self.interner) - 3]; + chalk_ir::Substitution::from(&self.interner, substitution) + } } /// Creates a `InternalSubsts` that maps each generic parameter to a higher-ranked diff --git a/src/librustc_traits/chalk/lowering.rs b/src/librustc_traits/chalk/lowering.rs index 5546a8db53395..e09359b8b3fc1 100644 --- a/src/librustc_traits/chalk/lowering.rs +++ b/src/librustc_traits/chalk/lowering.rs @@ -43,6 +43,8 @@ use rustc_span::def_id::DefId; use std::collections::btree_map::{BTreeMap, Entry}; +use chalk_ir::fold::shift::Shift; + /// Essentially an `Into` with a `&RustInterner` parameter crate trait LowerInto<'tcx, T> { /// Lower a rustc construct (e.g., `ty::TraitPredicate`) to a chalk type, consuming `self`. @@ -82,7 +84,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::InEnvironment LowerInto<'tcx, chalk_ir::InEnvironment LowerInto<'tcx, chalk_ir::InEnvironment LowerInto<'tcx, chalk_ir::InEnvironment Some( - chalk_ir::ProgramClauseData::Implies(chalk_ir::ProgramClauseImplication { - consequence: chalk_ir::DomainGoal::FromEnv(chalk_ir::FromEnv::Ty( - ty.lower_into(interner), - )), - conditions: chalk_ir::Goals::new(interner), - priority: chalk_ir::ClausePriority::High, - }) + chalk_ir::ProgramClauseData(chalk_ir::Binders::new( + chalk_ir::VariableKinds::new(interner), + chalk_ir::ProgramClauseImplication { + consequence: chalk_ir::DomainGoal::FromEnv(chalk_ir::FromEnv::Ty( + ty.lower_into(interner).shifted_in(interner), + )), + conditions: chalk_ir::Goals::new(interner), + priority: chalk_ir::ClausePriority::High, + }, + )) .intern(interner), ), }); @@ -416,12 +421,15 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { }) .intern(interner) } - // FIXME(chalk): add region - Dynamic(predicates, _region) => { - TyData::Dyn(chalk_ir::DynTy { bounds: predicates.lower_into(interner) }) - .intern(interner) - } - Closure(_def_id, _) => unimplemented!(), + Dynamic(predicates, region) => TyData::Dyn(chalk_ir::DynTy { + bounds: predicates.lower_into(interner), + lifetime: region.lower_into(interner), + }) + .intern(interner), + Closure(def_id, substs) => apply( + chalk_ir::TypeName::Closure(chalk_ir::ClosureId(def_id)), + substs.lower_into(interner), + ), Generator(_def_id, _substs, _) => unimplemented!(), GeneratorWitness(_) => unimplemented!(), Never => apply(chalk_ir::TypeName::Never, empty()), @@ -624,7 +632,7 @@ crate fn collect_bound_vars<'a, 'tcx, T: TypeFoldable<'tcx>>( } (0..parameters.len()).for_each(|i| { - parameters.get(&(i as u32)).expect("Skipped bound var index."); + parameters.get(&(i as u32)).expect(&format!("Skipped bound var index `{:?}`.", i)); }); let binders = chalk_ir::VariableKinds::from(interner, parameters.into_iter().map(|(_, v)| v)); diff --git a/src/librustc_traits/chalk/mod.rs b/src/librustc_traits/chalk/mod.rs index 6f657be0908b4..52ec0f2409dce 100644 --- a/src/librustc_traits/chalk/mod.rs +++ b/src/librustc_traits/chalk/mod.rs @@ -133,6 +133,7 @@ crate fn evaluate_goal<'tcx>( }, chalk_ir::TypeName::Array => unimplemented!(), chalk_ir::TypeName::FnDef(_) => unimplemented!(), + chalk_ir::TypeName::Closure(_) => unimplemented!(), chalk_ir::TypeName::Never => unimplemented!(), chalk_ir::TypeName::Tuple(_size) => unimplemented!(), chalk_ir::TypeName::Slice => unimplemented!(), diff --git a/src/test/ui/chalkify/closure.rs b/src/test/ui/chalkify/closure.rs new file mode 100644 index 0000000000000..81114d491d78e --- /dev/null +++ b/src/test/ui/chalkify/closure.rs @@ -0,0 +1,39 @@ +// check-fail +// compile-flags: -Z chalk + +fn main() -> () { + let t = || {}; + t(); + + let mut a = 0; + let mut b = move || { + a = 1; + }; + b(); + + let mut c = b; + + c(); + b(); + + let mut a = 0; + let mut b = || { + a = 1; + }; + b(); + + let mut c = b; + + c(); + b(); //~ ERROR + + // FIXME(chalk): this doesn't quite work + /* + let b = |c| { + c + }; + + let a = &32; + b(a); + */ +} diff --git a/src/test/ui/chalkify/closure.stderr b/src/test/ui/chalkify/closure.stderr new file mode 100644 index 0000000000000..d5a48a7dc6f95 --- /dev/null +++ b/src/test/ui/chalkify/closure.stderr @@ -0,0 +1,18 @@ +error[E0382]: borrow of moved value: `b` + --> $DIR/closure.rs:28:5 + | +LL | let mut c = b; + | - value moved here +... +LL | b(); + | ^ value borrowed here after move + | +note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `a` out of its environment + --> $DIR/closure.rs:21:9 + | +LL | a = 1; + | ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/chalkify/impl_wf.rs b/src/test/ui/chalkify/impl_wf.rs index fdc94f69bf21a..465eb10241ea2 100644 --- a/src/test/ui/chalkify/impl_wf.rs +++ b/src/test/ui/chalkify/impl_wf.rs @@ -23,15 +23,10 @@ impl Bar for Option { type Item = Option; } -// FIXME(chalk): the ordering of these two errors differs between CI and local -// We need to figure out why its non-deterministic -/* impl Bar for f32 { -//^ ERROR the trait bound `f32: Foo` is not satisfied type Item = f32; - //^ ERROR the trait bound `f32: Foo` is not satisfied + //~^ ERROR the trait bound `f32: Foo` is not satisfied } -*/ trait Baz where U: Foo { } diff --git a/src/test/ui/chalkify/impl_wf.stderr b/src/test/ui/chalkify/impl_wf.stderr index 5293bbaecd389..e5d7615e43e31 100644 --- a/src/test/ui/chalkify/impl_wf.stderr +++ b/src/test/ui/chalkify/impl_wf.stderr @@ -11,7 +11,18 @@ LL | impl Foo for str { } = note: to learn more, visit error[E0277]: the trait bound `f32: Foo` is not satisfied - --> $DIR/impl_wf.rs:40:6 + --> $DIR/impl_wf.rs:27:17 + | +LL | trait Bar { + | --- required by a bound in this +LL | type Item: Foo; + | --- required by this bound in `Bar` +... +LL | type Item = f32; + | ^^^ the trait `Foo` is not implemented for `f32` + +error[E0277]: the trait bound `f32: Foo` is not satisfied + --> $DIR/impl_wf.rs:35:6 | LL | trait Baz where U: Foo { } | --- required by this bound in `Baz` @@ -19,6 +30,6 @@ LL | trait Baz where U: Foo { } LL | impl Baz for f32 { } | ^^^^^^^^ the trait `Foo` is not implemented for `f32` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/chalkify/inherent_impl.rs b/src/test/ui/chalkify/inherent_impl.rs index 9dd9eb320ddd3..a2730219fbe2a 100644 --- a/src/test/ui/chalkify/inherent_impl.rs +++ b/src/test/ui/chalkify/inherent_impl.rs @@ -1,7 +1,5 @@ // run-pass // compile-flags: -Z chalk -// FIXME(chalk): remove when uncommented -#![allow(dead_code, unused_variables)] trait Foo { } @@ -11,8 +9,6 @@ struct S { x: T, } -// FIXME(chalk): need late-bound regions on FnDefs -/* fn only_foo(_x: &T) { } impl S { @@ -21,7 +17,6 @@ impl S { only_foo(&self.x) } } -*/ trait Bar { } impl Bar for u32 { } @@ -31,16 +26,10 @@ fn only_bar() { } impl S { // Test that the environment of `dummy_bar` adds up with the environment // of the inherent impl. - // FIXME(chalk): need late-bound regions on FnDefs - /* fn dummy_bar(&self) { only_foo(&self.x); only_bar::(); } - */ - fn dummy_bar() { - only_bar::(); - } } fn main() { @@ -48,10 +37,6 @@ fn main() { x: 5, }; - // FIXME(chalk): need late-bound regions on FnDefs - /* - s.dummy_foo(); s.dummy_bar::(); - */ - S::::dummy_bar::(); + s.dummy_foo(); } diff --git a/src/test/ui/chalkify/recursive_where_clause_on_type.rs b/src/test/ui/chalkify/recursive_where_clause_on_type.rs index 6ee13f5e7a104..87324a5f79bdd 100644 --- a/src/test/ui/chalkify/recursive_where_clause_on_type.rs +++ b/src/test/ui/chalkify/recursive_where_clause_on_type.rs @@ -1,5 +1,5 @@ // FIXME(chalk): should fail, see comments -// check-pass +// check-fail // compile-flags: -Z chalk #![feature(trivial_bounds)] @@ -10,7 +10,6 @@ trait Bar { trait Foo: Bar { } struct S where S: Foo; -//~^ WARN Trait bound S: Foo does not depend on any type or lifetime parameters impl Foo for S { } @@ -26,10 +25,6 @@ fn foo() { fn main() { // For some reason, the error is duplicated... - // FIXME(chalk): this order of this duplicate error seems non-determistic - // and causes test to fail - /* - foo::() // ERROR the type `S` is not well-formed (chalk) - //^ ERROR the type `S` is not well-formed (chalk) - */ + foo::() //~ ERROR the type `S` is not well-formed (chalk) + //~^ ERROR the type `S` is not well-formed (chalk) } diff --git a/src/test/ui/chalkify/recursive_where_clause_on_type.stderr b/src/test/ui/chalkify/recursive_where_clause_on_type.stderr index a5b7ef7fdb2e3..fddd58959278e 100644 --- a/src/test/ui/chalkify/recursive_where_clause_on_type.stderr +++ b/src/test/ui/chalkify/recursive_where_clause_on_type.stderr @@ -1,10 +1,14 @@ -warning: Trait bound S: Foo does not depend on any type or lifetime parameters - --> $DIR/recursive_where_clause_on_type.rs:12:19 +error: the type `S` is not well-formed (chalk) + --> $DIR/recursive_where_clause_on_type.rs:28:11 | -LL | struct S where S: Foo; - | ^^^ +LL | foo::() + | ^ + +error: the type `S` is not well-formed (chalk) + --> $DIR/recursive_where_clause_on_type.rs:28:5 | - = note: `#[warn(trivial_bounds)]` on by default +LL | foo::() + | ^^^^^^^^ -warning: 1 warning emitted +error: aborting due to 2 previous errors