diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index a33990813b820..e5b5dae551e87 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -427,6 +427,8 @@ pub(super) fn explicit_predicates_of<'tcx>( // supertrait). if let ty::Alias(ty::Projection, projection) = ty.kind() { projection.substs == trait_identity_substs + // FIXME(return_type_notation): This check should be more robust + && !tcx.is_impl_trait_in_trait(projection.def_id) && tcx.associated_item(projection.def_id).container_id(tcx) == def_id.to_def_id() } else { diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index 186ac536c6e5a..bfabd44bb5792 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -32,6 +32,7 @@ pub(super) fn check_fn<'a, 'tcx>( fn_def_id: LocalDefId, body: &'tcx hir::Body<'tcx>, can_be_generator: Option, + params_can_be_unsized: bool, ) -> Option> { let fn_id = fcx.tcx.hir().local_def_id_to_hir_id(fn_def_id); @@ -94,7 +95,7 @@ pub(super) fn check_fn<'a, 'tcx>( // The check for a non-trivial pattern is a hack to avoid duplicate warnings // for simple cases like `fn foo(x: Trait)`, // where we would error once on the parameter as a whole, and once on the binding `x`. - if param.pat.simple_ident().is_none() && !tcx.features().unsized_fn_params { + if param.pat.simple_ident().is_none() && !params_can_be_unsized { fcx.require_type_is_sized(param_ty, param.pat.span, traits::SizedArgumentType(ty_span)); } diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 7046269c2de22..9659a0ec13d40 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -89,6 +89,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr_def_id, body, closure.movability, + // Closure "rust-call" ABI doesn't support unsized params + false, ); let parent_substs = InternalSubsts::identity_for_item( diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 64426c4cbbb70..b97b55d8f7ee8 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -212,7 +212,7 @@ fn typeck_with_fallback<'tcx>( let fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig); let fn_sig = fcx.normalize(body.value.span, fn_sig); - check_fn(&mut fcx, fn_sig, decl, def_id, body, None); + check_fn(&mut fcx, fn_sig, decl, def_id, body, None, tcx.features().unsized_fn_params); } else { let expected_type = if let Some(&hir::Ty { kind: hir::TyKind::Infer, span, .. }) = body_ty { Some(fcx.next_ty_var(TypeVariableOrigin { diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 364269095e011..7425963d30ff8 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -323,7 +323,7 @@ provide! { tcx, def_id, other, cdata, extra_filename => { cdata.root.extra_filename.clone() } - traits_in_crate => { tcx.arena.alloc_from_iter(cdata.get_traits()) } + traits => { tcx.arena.alloc_from_iter(cdata.get_traits()) } trait_impls_in_crate => { tcx.arena.alloc_from_iter(cdata.get_trait_impls()) } implementations_of_trait => { cdata.get_implementations_of_trait(tcx, other) } crate_incoherent_impls => { cdata.get_incoherent_impls(tcx, other) } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 40723f4195988..f067bca4b0b39 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1938,7 +1938,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_traits(&mut self) -> LazyArray { empty_proc_macro!(self); - self.lazy_array(self.tcx.traits_in_crate(LOCAL_CRATE).iter().map(|def_id| def_id.index)) + self.lazy_array(self.tcx.traits(LOCAL_CRATE).iter().map(|def_id| def_id.index)) } /// Encodes an index, mapping each trait to its (local) implementations. @@ -2329,7 +2329,7 @@ pub fn provide(providers: &mut Providers) { .get(&def_id) .expect("no traits in scope for a doc link") }, - traits_in_crate: |tcx, LocalCrate| { + traits: |tcx, LocalCrate| { let mut traits = Vec::new(); for id in tcx.hir().items() { if matches!(tcx.def_kind(id.owner_id), DefKind::Trait | DefKind::TraitAlias) { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index f5b42c8048717..1528be42f6a18 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -38,7 +38,10 @@ use crate::traits::query::{ OutlivesBound, }; use crate::traits::specialization_graph; -use crate::traits::{self, ImplSource}; +use crate::traits::{ + CanonicalChalkEnvironmentAndGoal, CodegenObligationError, EvaluationResult, ImplSource, + ObjectSafetyViolation, ObligationCause, OverflowError, WellFormedLoc, +}; use crate::ty::fast_reject::SimplifiedType; use crate::ty::layout::ValidityRequirement; use crate::ty::subst::{GenericArg, SubstsRef}; @@ -1273,7 +1276,7 @@ rustc_queries! { query codegen_select_candidate( key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) - ) -> Result<&'tcx ImplSource<'tcx, ()>, traits::CodegenObligationError> { + ) -> Result<&'tcx ImplSource<'tcx, ()>, CodegenObligationError> { cache_on_disk_if { true } desc { |tcx| "computing candidate for `{}`", key.1 } } @@ -1294,7 +1297,7 @@ rustc_queries! { desc { |tcx| "building specialization graph of trait `{}`", tcx.def_path_str(trait_id) } cache_on_disk_if { true } } - query object_safety_violations(trait_id: DefId) -> &'tcx [traits::ObjectSafetyViolation] { + query object_safety_violations(trait_id: DefId) -> &'tcx [ObjectSafetyViolation] { desc { |tcx| "determining object safety of trait `{}`", tcx.def_path_str(trait_id) } } query check_is_object_safe(trait_id: DefId) -> bool { @@ -1838,8 +1841,7 @@ rustc_queries! { } /// A list of all traits in a crate, used by rustdoc and error reporting. - /// NOTE: Not named just `traits` due to a naming conflict. - query traits_in_crate(_: CrateNum) -> &'tcx [DefId] { + query traits(_: CrateNum) -> &'tcx [DefId] { desc { "fetching all traits in a crate" } separate_provide_extern } @@ -1953,12 +1955,12 @@ rustc_queries! { /// `infcx.predicate_must_hold()` instead. query evaluate_obligation( goal: CanonicalPredicateGoal<'tcx> - ) -> Result { + ) -> Result { desc { "evaluating trait selection obligation `{}`", goal.value.value } } query evaluate_goal( - goal: traits::CanonicalChalkEnvironmentAndGoal<'tcx> + goal: CanonicalChalkEnvironmentAndGoal<'tcx> ) -> Result< &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>, NoSolution @@ -2128,8 +2130,8 @@ rustc_queries! { /// all of the cases that the normal `ty::Ty`-based wfcheck does. This is fine, /// because the `ty::Ty`-based wfcheck is always run. query diagnostic_hir_wf_check( - key: (ty::Predicate<'tcx>, traits::WellFormedLoc) - ) -> &'tcx Option> { + key: (ty::Predicate<'tcx>, WellFormedLoc) + ) -> &'tcx Option> { arena_cache eval_always no_hash diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index bbea3e1412b00..5393dba8c2e19 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1199,7 +1199,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn all_traits(self) -> impl Iterator + 'tcx { iter::once(LOCAL_CRATE) .chain(self.crates(()).iter().copied()) - .flat_map(move |cnum| self.traits_in_crate(cnum).iter().copied()) + .flat_map(move |cnum| self.traits(cnum).iter().copied()) } #[inline] diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index dcfa33ae842e9..644bfd33970dc 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -177,14 +177,18 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { return Err(NoSolution); } - if goal.predicate.self_ty().has_non_region_infer() { + // The regions of a type don't affect the size of the type + let tcx = ecx.tcx(); + // We should erase regions from both the param-env and type, since both + // may have infer regions. Specifically, after canonicalizing and instantiating, + // early bound regions turn into region vars in both the new and old solver. + let key = tcx.erase_regions(goal.param_env.and(goal.predicate.self_ty())); + // But if there are inference variables, we have to wait until it's resolved. + if key.has_non_region_infer() { return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS); } - let tcx = ecx.tcx(); - let self_ty = tcx.erase_regions(goal.predicate.self_ty()); - - if let Ok(layout) = tcx.layout_of(goal.param_env.and(self_ty)) + if let Ok(layout) = tcx.layout_of(key) && layout.layout.is_pointer_like(&tcx.data_layout) { // FIXME: We could make this faster by making a no-constraints response diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index aa230936903f1..8bc82b9f54926 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -967,16 +967,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) { // The regions of a type don't affect the size of the type let tcx = self.tcx(); - let self_ty = - tcx.erase_regions(tcx.erase_late_bound_regions(obligation.predicate.self_ty())); - + let self_ty = tcx.erase_late_bound_regions(obligation.predicate.self_ty()); + // We should erase regions from both the param-env and type, since both + // may have infer regions. Specifically, after canonicalizing and instantiating, + // early bound regions turn into region vars in both the new and old solver. + let key = tcx.erase_regions(obligation.param_env.and(self_ty)); // But if there are inference variables, we have to wait until it's resolved. - if self_ty.has_non_region_infer() { + if key.has_non_region_infer() { candidates.ambiguous = true; return; } - if let Ok(layout) = tcx.layout_of(obligation.param_env.and(self_ty)) + if let Ok(layout) = tcx.layout_of(key) && layout.layout.is_pointer_like(&tcx.data_layout) { candidates.vec.push(BuiltinCandidate { has_nested: false }); diff --git a/tests/ui/associated-inherent-types/issue-111879-0.rs b/tests/ui/associated-inherent-types/issue-111879-0.rs new file mode 100644 index 0000000000000..e37f7d34ab5b8 --- /dev/null +++ b/tests/ui/associated-inherent-types/issue-111879-0.rs @@ -0,0 +1,14 @@ +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +// Check that we don't crash when printing inherent projections in diagnostics. + +pub struct Carrier<'a>(&'a ()); + +pub type User = for<'b> fn(Carrier<'b>::Focus); + +impl<'a> Carrier<'a> { + pub type Focus = &'a mut User; //~ ERROR overflow evaluating associated type +} + +fn main() {} diff --git a/tests/ui/associated-inherent-types/issue-111879-0.stderr b/tests/ui/associated-inherent-types/issue-111879-0.stderr new file mode 100644 index 0000000000000..7bdbad4401762 --- /dev/null +++ b/tests/ui/associated-inherent-types/issue-111879-0.stderr @@ -0,0 +1,8 @@ +error: overflow evaluating associated type `Carrier<'b>::Focus` + --> $DIR/issue-111879-0.rs:11:25 + | +LL | pub type Focus = &'a mut User; + | ^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/associated-inherent-types/issue-111879-1.rs b/tests/ui/associated-inherent-types/issue-111879-1.rs new file mode 100644 index 0000000000000..7acc4f945051e --- /dev/null +++ b/tests/ui/associated-inherent-types/issue-111879-1.rs @@ -0,0 +1,12 @@ +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +// Check that we don't crash when printing inherent projections in diagnostics. + +struct Foo(T); + +impl<'a> Foo { + type Assoc = &'a (); +} + +fn main(_: for<'a> fn(Foo::Assoc)) {} //~ ERROR `main` function has wrong type diff --git a/tests/ui/associated-inherent-types/issue-111879-1.stderr b/tests/ui/associated-inherent-types/issue-111879-1.stderr new file mode 100644 index 0000000000000..689b45e09aaac --- /dev/null +++ b/tests/ui/associated-inherent-types/issue-111879-1.stderr @@ -0,0 +1,12 @@ +error[E0580]: `main` function has wrong type + --> $DIR/issue-111879-1.rs:12:1 + | +LL | fn main(_: for<'a> fn(Foo::Assoc)) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters + | + = note: expected fn pointer `fn()` + found fn pointer `fn(for<'a> fn(Foo::Assoc))` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0580`. diff --git a/tests/ui/async-await/return-type-notation/supertrait-bound.rs b/tests/ui/async-await/return-type-notation/supertrait-bound.rs new file mode 100644 index 0000000000000..19bcfe3046bdc --- /dev/null +++ b/tests/ui/async-await/return-type-notation/supertrait-bound.rs @@ -0,0 +1,11 @@ +// check-pass + +#![feature(return_position_impl_trait_in_trait, return_type_notation)] +//~^ WARN the feature `return_type_notation` is incomplete and may not be safe to use + +trait IntFactory { + fn stream(&self) -> impl Iterator; +} +trait SendIntFactory: IntFactory + Send {} + +fn main() {} diff --git a/tests/ui/async-await/return-type-notation/supertrait-bound.stderr b/tests/ui/async-await/return-type-notation/supertrait-bound.stderr new file mode 100644 index 0000000000000..c8cec4946b4e4 --- /dev/null +++ b/tests/ui/async-await/return-type-notation/supertrait-bound.stderr @@ -0,0 +1,11 @@ +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/supertrait-bound.rs:3:49 + | +LL | #![feature(return_position_impl_trait_in_trait, return_type_notation)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/dyn-star/param-env-infer.current.stderr b/tests/ui/dyn-star/param-env-infer.current.stderr new file mode 100644 index 0000000000000..d0785c887d895 --- /dev/null +++ b/tests/ui/dyn-star/param-env-infer.current.stderr @@ -0,0 +1,18 @@ +warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/param-env-infer.rs:5:12 + | +LL | #![feature(dyn_star, pointer_like_trait)] + | ^^^^^^^^ + | + = note: see issue #102425 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0282]: type annotations needed + --> $DIR/param-env-infer.rs:12:10 + | +LL | t as _ + | ^ cannot infer type + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/dyn-star/param-env-infer.next.stderr b/tests/ui/dyn-star/param-env-infer.next.stderr new file mode 100644 index 0000000000000..d0785c887d895 --- /dev/null +++ b/tests/ui/dyn-star/param-env-infer.next.stderr @@ -0,0 +1,18 @@ +warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/param-env-infer.rs:5:12 + | +LL | #![feature(dyn_star, pointer_like_trait)] + | ^^^^^^^^ + | + = note: see issue #102425 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0282]: type annotations needed + --> $DIR/param-env-infer.rs:12:10 + | +LL | t as _ + | ^ cannot infer type + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/dyn-star/param-env-infer.rs b/tests/ui/dyn-star/param-env-infer.rs new file mode 100644 index 0000000000000..9039dde5e93e2 --- /dev/null +++ b/tests/ui/dyn-star/param-env-infer.rs @@ -0,0 +1,16 @@ +// revisions: current next +//[next] compile-flags: -Ztrait-solver=next +// incremental + +#![feature(dyn_star, pointer_like_trait)] +//~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes + +use std::fmt::Debug; +use std::marker::PointerLike; + +fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a { + t as _ + //~^ ERROR type annotations needed +} + +fn main() {} diff --git a/tests/ui/unsized-locals/issue-67981.rs b/tests/ui/unsized-locals/issue-67981.rs new file mode 100644 index 0000000000000..3eb6498e9dcff --- /dev/null +++ b/tests/ui/unsized-locals/issue-67981.rs @@ -0,0 +1,9 @@ +#![feature(unsized_fn_params)] + +fn main() { + let f: fn([u8]) = |_| {}; + //~^ERROR the size for values of type `[u8]` cannot be known at compilation time + let slice: Box<[u8]> = Box::new([1; 8]); + + f(*slice); +} diff --git a/tests/ui/unsized-locals/issue-67981.stderr b/tests/ui/unsized-locals/issue-67981.stderr new file mode 100644 index 0000000000000..a4b179ae2fd12 --- /dev/null +++ b/tests/ui/unsized-locals/issue-67981.stderr @@ -0,0 +1,15 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/issue-67981.rs:4:24 + | +LL | let f: fn([u8]) = |_| {}; + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | let f: fn([u8]) = |&_| {}; + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`.