diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index b18b59d9a752e..f18f1f4f8f0d6 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -12,7 +12,6 @@ use rustc_middle::bug; use rustc_middle::traits::solve::{ inspect, CanonicalInput, CanonicalResponse, Certainty, PredefinedOpaquesData, QueryResult, }; -use rustc_middle::traits::specialization_graph; use rustc_middle::ty::AliasRelationDirection; use rustc_middle::ty::TypeFolder; use rustc_middle::ty::{ @@ -900,16 +899,6 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { args } - pub(super) fn translate_args( - &self, - param_env: ty::ParamEnv<'tcx>, - source_impl: DefId, - source_args: ty::GenericArgsRef<'tcx>, - target_node: specialization_graph::Node, - ) -> ty::GenericArgsRef<'tcx> { - crate::traits::translate_args(self.infcx, param_env, source_impl, source_args, target_node) - } - pub(super) fn register_ty_outlives(&self, ty: Ty<'tcx>, lt: ty::Region<'tcx>) { self.infcx.register_region_obligation_with_cause(ty, lt, &ObligationCause::dummy()); } diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs index f9e164e1f3f97..c6d135a3c7fd3 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs @@ -1,4 +1,4 @@ -use crate::traits::specialization_graph; +use crate::traits::specialization_graph::{self, LeafDef, Node}; use super::assembly::structural_traits::AsyncCallableRelevantTypes; use super::assembly::{self, structural_traits, Candidate}; @@ -9,7 +9,6 @@ use rustc_infer::infer::InferCtxt; use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::solve::inspect::ProbeKind; use rustc_infer::traits::solve::MaybeCause; -use rustc_infer::traits::specialization_graph::LeafDef; use rustc_infer::traits::Reveal; use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal, QueryResult}; use rustc_middle::traits::BuiltinImplSource; @@ -235,14 +234,38 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { // // And then map these args to the args of the defining impl of `Assoc`, going // from `[u32, u64]` to `[u32, i32, u64]`. - let impl_args_with_gat = - goal.predicate.alias.args.rebase_onto(tcx, goal_trait_ref.def_id, impl_args); - let args = ecx.translate_args( - goal.param_env, - impl_def_id, - impl_args_with_gat, - assoc_def.defining_node, - ); + let args = match assoc_def.defining_node { + Node::Trait(_) => goal.predicate.alias.args, + Node::Impl(target_impl_def_id) => { + let impl_args_with_gat = goal.predicate.alias.args.rebase_onto( + tcx, + goal_trait_ref.def_id, + impl_args, + ); + if target_impl_def_id == impl_def_id { + // Same impl, no need to rebase. + impl_args_with_gat + } else { + let target_args = ecx.fresh_args_for_item(target_impl_def_id); + let target_trait_ref = tcx + .impl_trait_ref(target_impl_def_id) + .unwrap() + .instantiate(tcx, target_args); + // Relate source impl to target impl by equating trait refs. + ecx.eq(goal.param_env, impl_trait_ref, target_trait_ref)?; + // Also add predicates since they may be needed to constrain the + // target impl's params. + ecx.add_goals( + GoalSource::Misc, + tcx.predicates_of(target_impl_def_id) + .instantiate(tcx, target_args) + .into_iter() + .map(|(pred, _)| goal.with(tcx, pred)), + ); + impl_args_with_gat.rebase_onto(tcx, impl_def_id, target_args) + } + } + }; if !tcx.check_args_compatible(assoc_def.item.def_id, args) { return error_response( diff --git a/tests/ui/specialization/source-impl-requires-constraining-predicates-ambig.current.stderr b/tests/ui/specialization/source-impl-requires-constraining-predicates-ambig.current.stderr new file mode 100644 index 0000000000000..98b40eb42cb1f --- /dev/null +++ b/tests/ui/specialization/source-impl-requires-constraining-predicates-ambig.current.stderr @@ -0,0 +1,190 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/source-impl-requires-constraining-predicates-ambig.rs:13:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error: internal compiler error: compiler/rustc_trait_selection/src/traits/specialize/mod.rs:126:21: When translating generic parameters from DefId(0:9 ~ source_impl_requires_constraining_predicates_ambig[a0b3]::{impl#1}) to DefId(0:5 ~ source_impl_requires_constraining_predicates_ambig[a0b3]::{impl#0}), the expected specialization failed to hold + +thread 'rustc' panicked at compiler/rustc_trait_selection/src/traits/specialize/mod.rs:126:21: +Box +stack backtrace: + 0: std::panicking::begin_panic:: + at ./library/std/src/panicking.rs:693:12 + 1: std::panic::panic_any:: + at ./library/std/src/panic.rs:63:5 + 2: ::emit_producing_guarantee + at ./compiler/rustc_errors/src/diagnostic.rs:86:9 + 3: >::emit + at ./compiler/rustc_errors/src/diagnostic.rs:1320:9 + 4: ::bug:: + at ./compiler/rustc_errors/src/lib.rs:1121:9 + 5: {closure#0} + at ./compiler/rustc_middle/src/util/bug.rs:37:38 + 6: {closure#0}, !> + at ./compiler/rustc_middle/src/ty/context/tls.rs:158:23 + 7: with_context_opt, !>, !> + at ./compiler/rustc_middle/src/ty/context/tls.rs:101:18 + 8: rustc_middle::ty::context::tls::with_opt::::{closure#0}, !> + at ./compiler/rustc_middle/src/ty/context/tls.rs:156:5 + 9: rustc_middle::util::bug::opt_span_bug_fmt:: + at ./compiler/rustc_middle/src/util/bug.rs:31:5 + 10: rustc_middle::util::bug::bug_fmt + at ./compiler/rustc_middle/src/util/bug.rs:15:5 + 11: {closure#0} + at ./compiler/rustc_trait_selection/src/traits/specialize/mod.rs:126:21 + 12: unwrap_or_else<&rustc_middle::ty::list::RawList<(), rustc_middle::ty::generic_args::GenericArg>, (), rustc_trait_selection::traits::specialize::translate_args_with_cause::{closure_env#0}> + at ./library/core/src/result.rs:1456:23 + 13: translate_args_with_cause + at ./compiler/rustc_trait_selection/src/traits/specialize/mod.rs:124:13 + 14: confirm_impl_candidate + at ./compiler/rustc_trait_selection/src/traits/project.rs:2073:16 + 15: confirm_select_candidate + at ./compiler/rustc_trait_selection/src/traits/project.rs:1310:42 + 16: confirm_candidate + at ./compiler/rustc_trait_selection/src/traits/project.rs:1289:13 + 17: project + at ./compiler/rustc_trait_selection/src/traits/project.rs:732:36 + 18: opt_normalize_projection_term + at ./compiler/rustc_trait_selection/src/traits/project.rs:426:11 + 19: normalize_projection_ty + at ./compiler/rustc_trait_selection/src/traits/project.rs:302:5 + 20: fold_ty + at ./compiler/rustc_trait_selection/src/traits/normalize.rs:241:37 + 21: fold + at ./compiler/rustc_trait_selection/src/traits/normalize.rs:153:13 + 22: {closure#0} + at ./compiler/rustc_trait_selection/src/traits/normalize.rs:95:45 + 23: maybe_grow> + at /home/michael/.cargo/registry/src/index.crates.io-6f17d22bba15001f/stacker-0.1.15/src/lib.rs:55:9 + 24: ensure_sufficient_stack> + at ./compiler/rustc_data_structures/src/stack.rs:17:5 + 25: normalize_with_depth_to + at ./compiler/rustc_trait_selection/src/traits/normalize.rs:95:18 + 26: normalize_with_depth + at ./compiler/rustc_trait_selection/src/traits/normalize.rs:77:17 + 27: normalize + at ./compiler/rustc_trait_selection/src/traits/normalize.rs:28:17 + 28: normalize + at ./compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs:352:13 + 29: record_ty + at ./compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs:339:13 + 30: {closure#0} + at ./compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs:2243:9 + 31: lower_ty_common + at ./compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs:2041:5 + 32: lower_ty + at ./compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs:407:18 + 33: declare + at ./compiler/rustc_hir_typeck/src/gather_locals.rs:92:28 + 34: visit_local + at ./compiler/rustc_hir_typeck/src/gather_locals.rs:119:9 + 35: walk_block + at ./compiler/rustc_hir/src/intravisit.rs:632:5 + 36: walk_expr + 37: check_fn + at ./compiler/rustc_hir_typeck/src/check.rs:57:5 + 38: {closure#0} + at ./compiler/rustc_hir_typeck/src/lib.rs:159:9 + 39: typeck_with_fallback + at ./compiler/rustc_hir_typeck/src/lib.rs:114:1 + 40: {closure#0} + at ./compiler/rustc_query_impl/src/plumbing.rs:281:9 + [... omitted 22 frames ...] + 41: query_ensure>> + at ./compiler/rustc_middle/src/query/plumbing.rs:161:9 + 42: typeck + at ./compiler/rustc_middle/src/query/plumbing.rs:196:9 + 43: {closure#4} + at ./compiler/rustc_hir_analysis/src/lib.rs:200:13 + 44: {closure#0} + at ./compiler/rustc_middle/src/hir/map/mod.rs:347:82 + 45: {closure#0}<&rustc_span::def_id::LocalDefId, &[rustc_span::def_id::LocalDefId], rustc_middle::hir::map::{impl#3}::par_body_owners::{closure_env#0}> + at ./compiler/rustc_data_structures/src/sync/parallel.rs:182:34 + 46: call_once<(), rustc_data_structures::sync::parallel::enabled::par_for_each_in::{closure#0}::{closure#0}::{closure_env#0}<&rustc_span::def_id::LocalDefId, &[rustc_span::def_id::LocalDefId], rustc_middle::hir::map::{impl#3}::par_body_owners::{closure_env#0}>> + at ./library/core/src/panic/unwind_safe.rs:272:9 + 47: do_call>>, ()> + at ./library/std/src/panicking.rs:559:40 + 48: try<(), core::panic::unwind_safe::AssertUnwindSafe>>> + at ./library/std/src/panicking.rs:523:19 + 49: run<(), rustc_data_structures::sync::parallel::enabled::par_for_each_in::{closure#0}::{closure#1}::{closure_env#0}<&rustc_span::def_id::LocalDefId, &[rustc_span::def_id::LocalDefId], rustc_middle::hir::map::{impl#3}::par_body_owners::{closure_env#0}>> + at ./compiler/rustc_data_structures/src/sync/parallel.rs:28:9 + 50: {closure#1}<&rustc_span::def_id::LocalDefId, &[rustc_span::def_id::LocalDefId], rustc_middle::hir::map::{impl#3}::par_body_owners::{closure_env#0}> + at ./compiler/rustc_data_structures/src/sync/parallel.rs:186:21 + 51: for_each>> + at ./library/core/src/slice/iter/macros.rs:252:21 + 52: {closure#0}<&rustc_span::def_id::LocalDefId, &[rustc_span::def_id::LocalDefId], rustc_middle::hir::map::{impl#3}::par_body_owners::{closure_env#0}> + at ./compiler/rustc_data_structures/src/sync/parallel.rs:185:17 + 53: parallel_guard<(), rustc_data_structures::sync::parallel::enabled::par_for_each_in::{closure_env#0}<&rustc_span::def_id::LocalDefId, &[rustc_span::def_id::LocalDefId], rustc_middle::hir::map::{impl#3}::par_body_owners::{closure_env#0}>> + at ./compiler/rustc_data_structures/src/sync/parallel.rs:44:15 + 54: par_for_each_in<&rustc_span::def_id::LocalDefId, &[rustc_span::def_id::LocalDefId], rustc_middle::hir::map::{impl#3}::par_body_owners::{closure_env#0}> + at ./compiler/rustc_data_structures/src/sync/parallel.rs:178:9 + 55: par_body_owners + at ./compiler/rustc_middle/src/hir/map/mod.rs:347:9 + 56: check_crate + at ./compiler/rustc_hir_analysis/src/lib.rs:197:5 + 57: run_required_analyses + at ./compiler/rustc_interface/src/passes.rs:734:5 + 58: analysis + at ./compiler/rustc_interface/src/passes.rs:773:5 + 59: {closure#0} + at ./compiler/rustc_query_impl/src/plumbing.rs:281:9 + [... omitted 22 frames ...] + 60: query_get_at>> + at ./compiler/rustc_middle/src/query/plumbing.rs:145:17 + 61: analysis + at ./compiler/rustc_middle/src/query/plumbing.rs:423:31 + 62: analysis + at ./compiler/rustc_middle/src/query/plumbing.rs:414:17 + 63: {closure#3} + at ./compiler/rustc_driver_impl/src/lib.rs:439:48 + 64: {closure#1}> + at ./compiler/rustc_middle/src/ty/context.rs:882:37 + 65: {closure#0}>, core::result::Result<(), rustc_span::ErrorGuaranteed>> + at ./compiler/rustc_middle/src/ty/context/tls.rs:82:9 + 66: try_with, rustc_middle::ty::context::tls::enter_context::{closure_env#0}>, core::result::Result<(), rustc_span::ErrorGuaranteed>>, core::result::Result<(), rustc_span::ErrorGuaranteed>> + at ./library/std/src/thread/local.rs:286:12 + 67: with, rustc_middle::ty::context::tls::enter_context::{closure_env#0}>, core::result::Result<(), rustc_span::ErrorGuaranteed>>, core::result::Result<(), rustc_span::ErrorGuaranteed>> + at ./library/std/src/thread/local.rs:262:9 + 68: enter_context>, core::result::Result<(), rustc_span::ErrorGuaranteed>> + at ./compiler/rustc_middle/src/ty/context/tls.rs:79:5 + 69: enter> + at ./compiler/rustc_middle/src/ty/context.rs:882:9 + 70: {closure#1} + at ./compiler/rustc_driver_impl/src/lib.rs:439:13 + 71: enter, rustc_span::ErrorGuaranteed>> + at ./compiler/rustc_interface/src/queries.rs:315:19 + 72: {closure#0} + at ./compiler/rustc_driver_impl/src/lib.rs:387:22 + 73: {closure#1}, rustc_driver_impl::run_compiler::{closure_env#0}> + at ./compiler/rustc_interface/src/interface.rs:503:27 + 74: {closure#0}, rustc_driver_impl::run_compiler::{closure_env#0}>, core::result::Result<(), rustc_span::ErrorGuaranteed>> + at ./compiler/rustc_interface/src/util.rs:154:13 + 75: {closure#0}, rustc_driver_impl::run_compiler::{closure_env#0}>, core::result::Result<(), rustc_span::ErrorGuaranteed>>, core::result::Result<(), rustc_span::ErrorGuaranteed>> + at ./compiler/rustc_interface/src/util.rs:106:21 + 76: set, rustc_driver_impl::run_compiler::{closure_env#0}>, core::result::Result<(), rustc_span::ErrorGuaranteed>>, core::result::Result<(), rustc_span::ErrorGuaranteed>>, core::result::Result<(), rustc_span::ErrorGuaranteed>> + at /home/michael/.cargo/registry/src/index.crates.io-6f17d22bba15001f/scoped-tls-1.0.1/src/lib.rs:137:9 + 77: create_session_globals_then, rustc_interface::util::run_in_thread_with_globals::{closure#0}::{closure#0}::{closure_env#0}, rustc_driver_impl::run_compiler::{closure_env#0}>, core::result::Result<(), rustc_span::ErrorGuaranteed>>, core::result::Result<(), rustc_span::ErrorGuaranteed>>> + at ./compiler/rustc_span/src/lib.rs:134:5 + 78: {closure#0}, rustc_driver_impl::run_compiler::{closure_env#0}>, core::result::Result<(), rustc_span::ErrorGuaranteed>>, core::result::Result<(), rustc_span::ErrorGuaranteed>> + at ./compiler/rustc_interface/src/util.rs:105:17 +note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace. + +note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md + +note: please make sure that you have updated to the latest nightly + +note: rustc 1.80.0-dev running on x86_64-unknown-linux-gnu + +note: compiler flags: -Z threads=1 -Z simulate-remapped-rust-src-base=/rustc/FAKE_PREFIX -Z translate-remapped-path-to-local-path=no -Z ignore-directory-in-diagnostics-source-blocks=/home/michael/.cargo -Z ignore-directory-in-diagnostics-source-blocks=/home/michael/programming/rust2/vendor -C codegen-units=1 -Z ui-testing -Z deduplicate-diagnostics=no -Z write-long-types-to-disk=no -C strip=debuginfo -C prefer-dynamic -C rpath -C debuginfo=0 + +query stack during panic: +#0 [typeck] type-checking `main` +#1 [analysis] running analysis passes on this crate +end of query stack +error: aborting due to 1 previous error; 1 warning emitted + diff --git a/tests/ui/specialization/source-impl-requires-constraining-predicates-ambig.next.stderr b/tests/ui/specialization/source-impl-requires-constraining-predicates-ambig.next.stderr new file mode 100644 index 0000000000000..7d6abdfd234a7 --- /dev/null +++ b/tests/ui/specialization/source-impl-requires-constraining-predicates-ambig.next.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/source-impl-requires-constraining-predicates-ambig.rs:13:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/source-impl-requires-constraining-predicates-ambig.rs b/tests/ui/specialization/source-impl-requires-constraining-predicates-ambig.rs new file mode 100644 index 0000000000000..2ace1898798fc --- /dev/null +++ b/tests/ui/specialization/source-impl-requires-constraining-predicates-ambig.rs @@ -0,0 +1,28 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] check-pass +//@[current] known-bug: unknown +//@[current] failure-status: 101 + +// Tests that rebasing from the concrete impl to the default impl also processes the +// `[u32; 0]: IntoIterator` predicate to constrain the `?U` impl arg. +// This test also makes sure that we don't do anything weird when rebasing the args +// is ambiguous. + +#![feature(specialization)] +//[next]~^ WARN the feature `specialization` is incomplete + +trait Spec { + type Assoc; +} + +default impl Spec for T where T: IntoIterator { + type Assoc = U; +} + +impl Spec for [T; 0] {} + +fn main() { + let x: <[_; 0] as Spec>::Assoc = 1; +} diff --git a/tests/ui/specialization/source-impl-requires-constraining-predicates.current.stderr b/tests/ui/specialization/source-impl-requires-constraining-predicates.current.stderr new file mode 100644 index 0000000000000..3442e5b5ca616 --- /dev/null +++ b/tests/ui/specialization/source-impl-requires-constraining-predicates.current.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/source-impl-requires-constraining-predicates.rs:9:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/source-impl-requires-constraining-predicates.next.stderr b/tests/ui/specialization/source-impl-requires-constraining-predicates.next.stderr new file mode 100644 index 0000000000000..3442e5b5ca616 --- /dev/null +++ b/tests/ui/specialization/source-impl-requires-constraining-predicates.next.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/source-impl-requires-constraining-predicates.rs:9:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/source-impl-requires-constraining-predicates.rs b/tests/ui/specialization/source-impl-requires-constraining-predicates.rs new file mode 100644 index 0000000000000..532fc36764068 --- /dev/null +++ b/tests/ui/specialization/source-impl-requires-constraining-predicates.rs @@ -0,0 +1,24 @@ +//@ check-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +// Tests that rebasing from the concrete impl to the default impl also processes the +// `[u32; 0]: IntoIterator` predicate to constrain the `?U` impl arg. + +#![feature(specialization)] +//~^ WARN the feature `specialization` is incomplete + +trait Spec { + type Assoc; +} + +default impl Spec for T where T: IntoIterator { + type Assoc = U; +} + +impl Spec for [T; 0] {} + +fn main() { + let x: <[u32; 0] as Spec>::Assoc = 1; +}