diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index a1e906140e0e..8b0e7794f92a 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -977,7 +977,6 @@ impl<'tcx> TraitRef<'tcx> { substs: SubstsRef<'tcx>, ) -> ty::TraitRef<'tcx> { let defs = tcx.generics_of(trait_id); - ty::TraitRef { def_id: trait_id, substs: tcx.intern_substs(&substs[..defs.params.len()]) } } } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index a277f74f7a43..d05f62ea29e4 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -4,7 +4,7 @@ use super::{ use crate::infer::InferCtxt; use rustc_hir as hir; use rustc_hir::def_id::DefId; -use rustc_middle::ty::subst::Subst; +use rustc_middle::ty::subst::{Subst, SubstsRef}; use rustc_middle::ty::{self, GenericParamDefKind}; use rustc_span::symbol::sym; use std::iter; @@ -17,7 +17,7 @@ crate trait InferCtxtExt<'tcx> { &self, trait_ref: ty::PolyTraitRef<'tcx>, obligation: &PredicateObligation<'tcx>, - ) -> Option; + ) -> Option<(DefId, SubstsRef<'tcx>)>; /*private*/ fn describe_enclosure(&self, hir_id: hir::HirId) -> Option<&'static str>; @@ -34,7 +34,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { &self, trait_ref: ty::PolyTraitRef<'tcx>, obligation: &PredicateObligation<'tcx>, - ) -> Option { + ) -> Option<(DefId, SubstsRef<'tcx>)> { let tcx = self.tcx; let param_env = obligation.param_env; let trait_ref = tcx.erase_late_bound_regions(trait_ref); @@ -50,7 +50,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let impl_self_ty = impl_trait_ref.self_ty(); if let Ok(..) = self.can_eq(param_env, trait_self_ty, impl_self_ty) { - self_match_impls.push(def_id); + self_match_impls.push((def_id, impl_substs)); if iter::zip( trait_ref.substs.types().skip(1), @@ -58,12 +58,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ) .all(|(u, v)| self.fuzzy_match_tys(u, v, false).is_some()) { - fuzzy_match_impls.push(def_id); + fuzzy_match_impls.push((def_id, impl_substs)); } } }); - let impl_def_id = if self_match_impls.len() == 1 { + let impl_def_id_and_substs = if self_match_impls.len() == 1 { self_match_impls[0] } else if fuzzy_match_impls.len() == 1 { fuzzy_match_impls[0] @@ -71,7 +71,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { return None; }; - tcx.has_attr(impl_def_id, sym::rustc_on_unimplemented).then_some(impl_def_id) + tcx.has_attr(impl_def_id_and_substs.0, sym::rustc_on_unimplemented) + .then_some(impl_def_id_and_substs) } /// Used to set on_unimplemented's `ItemContext` @@ -120,8 +121,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { trait_ref: ty::PolyTraitRef<'tcx>, obligation: &PredicateObligation<'tcx>, ) -> OnUnimplementedNote { - let def_id = - self.impl_similar_to(trait_ref, obligation).unwrap_or_else(|| trait_ref.def_id()); + let (def_id, substs) = self + .impl_similar_to(trait_ref, obligation) + .unwrap_or_else(|| (trait_ref.def_id(), trait_ref.skip_binder().substs)); let trait_ref = trait_ref.skip_binder(); let mut flags = vec![( @@ -176,7 +178,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { for param in generics.params.iter() { let value = match param.kind { GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { - trait_ref.substs[param.index as usize].to_string() + substs[param.index as usize].to_string() } GenericParamDefKind::Lifetime => continue, }; @@ -184,7 +186,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { flags.push((name, Some(value))); if let GenericParamDefKind::Type { .. } = param.kind { - let param_ty = trait_ref.substs[param.index as usize].expect_ty(); + let param_ty = substs[param.index as usize].expect_ty(); if let Some(def) = param_ty.ty_adt_def() { // We also want to be able to select the parameter's // original signature with no type arguments resolved diff --git a/src/test/ui/consts/issue-94675.rs b/src/test/ui/consts/issue-94675.rs new file mode 100644 index 000000000000..0604aab3bcd2 --- /dev/null +++ b/src/test/ui/consts/issue-94675.rs @@ -0,0 +1,16 @@ +#![feature(const_trait_impl, const_mut_refs)] + +struct Foo<'a> { + bar: &'a mut Vec, +} + +impl<'a> Foo<'a> { + const fn spam(&mut self, baz: &mut Vec) { + self.bar[0] = baz.len(); + //~^ ERROR cannot call non-const fn `Vec::::len` in constant functions + //~| ERROR the trait bound `Vec: ~const IndexMut` is not satisfied + //~| ERROR cannot call non-const operator in constant functions + } +} + +fn main() {} diff --git a/src/test/ui/consts/issue-94675.stderr b/src/test/ui/consts/issue-94675.stderr new file mode 100644 index 000000000000..6665e42835b7 --- /dev/null +++ b/src/test/ui/consts/issue-94675.stderr @@ -0,0 +1,38 @@ +error[E0015]: cannot call non-const fn `Vec::::len` in constant functions + --> $DIR/issue-94675.rs:9:27 + | +LL | self.bar[0] = baz.len(); + | ^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error[E0277]: the trait bound `Vec: ~const IndexMut` is not satisfied + --> $DIR/issue-94675.rs:9:9 + | +LL | self.bar[0] = baz.len(); + | ^^^^^^^^^^^ vector indices are of type `usize` or ranges of `usize` + | + = help: the trait `~const IndexMut` is not implemented for `Vec` +note: the trait `IndexMut` is implemented for `Vec`, but that implementation is not `const` + --> $DIR/issue-94675.rs:9:9 + | +LL | self.bar[0] = baz.len(); + | ^^^^^^^^^^^ + +error[E0015]: cannot call non-const operator in constant functions + --> $DIR/issue-94675.rs:9:9 + | +LL | self.bar[0] = baz.len(); + | ^^^^^^^^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + | +LL | impl, A: Allocator> IndexMut for Vec { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0015, E0277. +For more information about an error, try `rustc --explain E0015`. diff --git a/src/test/ui/issues/issue-87707.rs b/src/test/ui/issues/issue-87707.rs index d2e9343f86cd..26e9e2c8f91c 100644 --- a/src/test/ui/issues/issue-87707.rs +++ b/src/test/ui/issues/issue-87707.rs @@ -1,6 +1,7 @@ // test for #87707 // edition:2018 // run-fail +// exec-env:RUST_BACKTRACE=0 // check-run-results use std::sync::Once; diff --git a/src/test/ui/issues/issue-87707.run.stderr b/src/test/ui/issues/issue-87707.run.stderr index 8f82ccc0c2ab..e6c9ea0eb53c 100644 --- a/src/test/ui/issues/issue-87707.run.stderr +++ b/src/test/ui/issues/issue-87707.run.stderr @@ -1,3 +1,3 @@ -thread 'main' panicked at 'Here Once instance is poisoned.', $DIR/issue-87707.rs:12:24 +thread 'main' panicked at 'Here Once instance is poisoned.', $DIR/issue-87707.rs:13:24 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -thread 'main' panicked at 'Once instance has previously been poisoned', $DIR/issue-87707.rs:14:7 +thread 'main' panicked at 'Once instance has previously been poisoned', $DIR/issue-87707.rs:15:7