1
Fork 0

Auto merge of #82153 - jonas-schievink:rollup-ls5r943, r=jonas-schievink

Rollup of 19 pull requests

Successful merges:

 - #81503 (Suggest to create a new `const` item if the `fn` in the array is a `const fn`)
 - #81897 (Add match pattern diagnostics regression test)
 - #81975 (Seal the CommandExt, OsStrExt and OsStringExt traits)
 - #82009 (const_generics: Dont evaluate array length const when handling errors)
 - #82060 (Fix typos in BTreeSet::{first, last} docs)
 - #82061 (CTFE validation: catch ReadPointerAsBytes and better error)
 - #82063 (Fixed minor typo in catch_unwind docs)
 - #82067 (const_generics: Fix incorrect ty::ParamEnv::empty() usage)
 - #82077 (Edit `rustc_arena::DropArena` docs)
 - #82096 (Fix a typo)
 - #82106 (Remove unnecessary `Option` in `default_doc`)
 - #82107 (expand: Some cleanup)
 - #82118 (Add missing env!-decl variant)
 - #82119 (Fix typo in link to CreateSymbolicLinkW documentation.)
 - #82120 (Stabilize Arguments::as_str)
 - #82129 (Remove redundant bool_to_option feature gate)
 - #82133 (Update link for extern prelude.)
 - #82141 (32-bit ARM: Emit `lr` instead of `r14` when specified as an `asm!` output register.)
 - #82147 (⬆️ rust-analyzer)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2021-02-16 02:14:13 +00:00
commit 42a4673fbd
50 changed files with 351 additions and 136 deletions

View file

@ -568,10 +568,13 @@ impl Drop for DropType {
}
/// An arena which can be used to allocate any type.
///
/// # Safety
///
/// Allocating in this arena is unsafe since the type system
/// doesn't know which types it contains. In order to
/// allocate safely, you must store a PhantomData<T>
/// alongside this arena for each type T you allocate.
/// allocate safely, you must store a `PhantomData<T>`
/// alongside this arena for each type `T` you allocate.
#[derive(Default)]
pub struct DropArena {
/// A list of destructors to run when the arena drops.
@ -589,7 +592,7 @@ impl DropArena {
ptr::write(mem, object);
let result = &mut *mem;
// Record the destructor after doing the allocation as that may panic
// and would cause `object`'s destructor to run twice if it was recorded before
// and would cause `object`'s destructor to run twice if it was recorded before.
self.destructors
.borrow_mut()
.push(DropType { drop_fn: drop_for_type::<T>, obj: result as *mut T as *mut u8 });
@ -607,16 +610,16 @@ impl DropArena {
let start_ptr = self.arena.alloc_raw(Layout::array::<T>(len).unwrap()) as *mut T;
let mut destructors = self.destructors.borrow_mut();
// Reserve space for the destructors so we can't panic while adding them
// Reserve space for the destructors so we can't panic while adding them.
destructors.reserve(len);
// Move the content to the arena by copying it and then forgetting
// the content of the SmallVec
// the content of the SmallVec.
vec.as_ptr().copy_to_nonoverlapping(start_ptr, len);
mem::forget(vec.drain(..));
// Record the destructors after doing the allocation as that may panic
// and would cause `object`'s destructor to run twice if it was recorded before
// and would cause `object`'s destructor to run twice if it was recorded before.
for i in 0..len {
destructors
.push(DropType { drop_fn: drop_for_type::<T>, obj: start_ptr.add(i) as *mut u8 });

View file

@ -487,6 +487,9 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>)
} else if reg == InlineAsmReg::AArch64(AArch64InlineAsmReg::x30) {
// LLVM doesn't recognize x30
"{lr}".to_string()
} else if reg == InlineAsmReg::Arm(ArmInlineAsmReg::r14) {
// LLVM doesn't recognize r14
"{lr}".to_string()
} else {
format!("{{{}}}", reg.name())
}

View file

@ -1067,8 +1067,6 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
self.cfg.configure_expr(expr);
visit_clobber(expr.deref_mut(), |mut expr| {
self.cfg.configure_expr_kind(&mut expr.kind);
if let Some(attr) = self.take_first_attr(&mut expr) {
// Collect the invoc regardless of whether or not attributes are permitted here
// expansion will eat the attribute so it won't error later.
@ -1166,8 +1164,6 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
let expr = configure!(self, expr);
expr.filter_map(|mut expr| {
self.cfg.configure_expr_kind(&mut expr.kind);
if let Some(attr) = self.take_first_attr(&mut expr) {
self.cfg.maybe_emit_expr_attr_err(&attr.0);
@ -1192,7 +1188,6 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
}
fn visit_pat(&mut self, pat: &mut P<ast::Pat>) {
self.cfg.configure_pat(pat);
match pat.kind {
PatKind::MacCall(_) => {}
_ => return noop_visit_pat(pat, self),
@ -1406,15 +1401,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
});
}
fn visit_foreign_mod(&mut self, foreign_mod: &mut ast::ForeignMod) {
self.cfg.configure_foreign_mod(foreign_mod);
noop_visit_foreign_mod(foreign_mod, self);
}
fn flat_map_foreign_item(
&mut self,
mut foreign_item: P<ast::ForeignItem>,
foreign_item: P<ast::ForeignItem>,
) -> SmallVec<[P<ast::ForeignItem>; 1]> {
let mut foreign_item = configure!(self, foreign_item);
if let Some(attr) = self.take_first_attr(&mut foreign_item) {
return self
.collect_attr(
@ -1439,11 +1431,6 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
}
}
fn visit_item_kind(&mut self, item: &mut ast::ItemKind) {
self.cfg.configure_item_kind(item);
noop_visit_item_kind(item, self);
}
fn flat_map_generic_param(
&mut self,
param: ast::GenericParam,
@ -1602,11 +1589,6 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
*id = self.cx.resolver.next_node_id()
}
}
fn visit_fn_decl(&mut self, mut fn_decl: &mut P<ast::FnDecl>) {
self.cfg.configure_fn_decl(&mut fn_decl);
noop_visit_fn_decl(fn_decl, self);
}
}
pub struct ExpansionConfig<'feat> {
@ -1614,9 +1596,8 @@ pub struct ExpansionConfig<'feat> {
pub features: Option<&'feat Features>,
pub recursion_limit: Limit,
pub trace_mac: bool,
pub should_test: bool, // If false, strip `#[test]` nodes
pub keep_macs: bool,
pub span_debug: bool, // If true, use verbose debugging for `proc_macro::Span`
pub should_test: bool, // If false, strip `#[test]` nodes
pub span_debug: bool, // If true, use verbose debugging for `proc_macro::Span`
pub proc_macro_backtrace: bool, // If true, show backtraces for proc-macro panics
}
@ -1628,7 +1609,6 @@ impl<'feat> ExpansionConfig<'feat> {
recursion_limit: Limit::new(1024),
trace_mac: false,
should_test: false,
keep_macs: false,
span_debug: false,
proc_macro_backtrace: false,
}

View file

@ -1,4 +1,3 @@
#![feature(bool_to_option)]
#![feature(crate_visibility_modifier)]
#![feature(decl_macro)]
#![feature(or_patterns)]

View file

@ -371,12 +371,4 @@ impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> {
}
}
}
fn visit_mod(&mut self, module: &mut ast::Mod) {
noop_visit_mod(module, self);
// remove macro definitions
module.items.retain(
|item| !matches!(item.kind, ast::ItemKind::MacCall(_) if !self.cx.ecfg.keep_macs),
);
}
}

View file

@ -639,6 +639,10 @@ struct QueryTypeRelatingDelegate<'a, 'tcx> {
}
impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> {
fn param_env(&self) -> ty::ParamEnv<'tcx> {
self.param_env
}
fn create_next_universe(&mut self) -> ty::UniverseIndex {
self.infcx.create_next_universe()
}

View file

@ -221,6 +221,7 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> {
/// As `3 + 4` contains `N` in its substs, this must not succeed.
///
/// See `src/test/ui/const-generics/occurs-check/` for more examples where this is relevant.
#[instrument(level = "debug", skip(self))]
fn unify_const_variable(
&self,
param_env: ty::ParamEnv<'tcx>,

View file

@ -72,6 +72,8 @@ where
}
pub trait TypeRelatingDelegate<'tcx> {
fn param_env(&self) -> ty::ParamEnv<'tcx>;
/// Push a constraint `sup: sub` -- this constraint must be
/// satisfied for the two types to be related. `sub` and `sup` may
/// be regions from the type or new variables created through the
@ -473,9 +475,8 @@ where
self.infcx.tcx
}
// FIXME(oli-obk): not sure how to get the correct ParamEnv
fn param_env(&self) -> ty::ParamEnv<'tcx> {
ty::ParamEnv::empty()
self.delegate.param_env()
}
fn tag(&self) -> &'static str {
@ -819,9 +820,8 @@ where
self.infcx.tcx
}
// FIXME(oli-obk): not sure how to get the correct ParamEnv
fn param_env(&self) -> ty::ParamEnv<'tcx> {
ty::ParamEnv::empty()
self.delegate.param_env()
}
fn tag(&self) -> &'static str {

View file

@ -31,6 +31,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// constant `bar::<T>()` requires a substitution for `T`, if the substitution for `T` is still
/// too generic for the constant to be evaluated then `Err(ErrorHandled::TooGeneric)` is
/// returned.
#[instrument(level = "debug", skip(self))]
pub fn const_eval_resolve(
self,
param_env: ty::ParamEnv<'tcx>,

View file

@ -228,7 +228,10 @@ pub enum ObligationCauseCode<'tcx> {
/// Inline asm operand type must be `Sized`.
InlineAsmSized,
/// `[T, ..n]` implies that `T` must be `Copy`.
RepeatVec,
/// If the function in the array repeat expression is a `const fn`,
/// display a help message suggesting to move the function call to a
/// new `const` item while saying that `T` doesn't implement `Copy`.
RepeatVec(bool),
/// Types of fields (other than the last, except for packed structs) in a struct must be sized.
FieldSized {

View file

@ -228,12 +228,17 @@ impl<'tcx> ty::TyS<'tcx> {
ty::Adt(def, _) => format!("{} `{}`", def.descr(), tcx.def_path_str(def.did)).into(),
ty::Foreign(def_id) => format!("extern type `{}`", tcx.def_path_str(def_id)).into(),
ty::Array(t, n) => {
let n = tcx.lift(n).unwrap();
match n.try_eval_usize(tcx, ty::ParamEnv::empty()) {
_ if t.is_simple_ty() => format!("array `{}`", self).into(),
Some(n) => format!("array of {} element{}", n, pluralize!(n)).into(),
None => "array".into(),
if t.is_simple_ty() {
return format!("array `{}`", self).into();
}
let n = tcx.lift(n).unwrap();
if let ty::ConstKind::Value(v) = n.val {
if let Some(n) = v.try_to_machine_usize(tcx) {
return format!("array of {} element{}", n, pluralize!(n)).into();
}
}
"array".into()
}
ty::Slice(ty) if ty.is_simple_ty() => format!("slice `{}`", self).into(),
ty::Slice(_) => "slice".into(),

View file

@ -347,6 +347,7 @@ impl<'tcx> Instance<'tcx> {
}
// This should be kept up to date with `resolve`.
#[instrument(level = "debug", skip(tcx))]
pub fn resolve_opt_const_arg(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,

View file

@ -43,6 +43,9 @@ use rustc_trait_selection::traits::{self, ObligationCause, PredicateObligations}
use crate::dataflow::impls::MaybeInitializedPlaces;
use crate::dataflow::move_paths::MoveData;
use crate::dataflow::ResultsCursor;
use crate::transform::{
check_consts::ConstCx, promote_consts::is_const_fn_in_array_repeat_expression,
};
use crate::borrow_check::{
borrow_set::BorrowSet,
@ -1098,6 +1101,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
) -> Fallible<()> {
relate_tys::relate_types(
self.infcx,
self.param_env,
a,
v,
b,
@ -1988,18 +1992,24 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
Operand::Copy(..) | Operand::Constant(..) => {
// These are always okay: direct use of a const, or a value that can evidently be copied.
}
Operand::Move(_) => {
Operand::Move(place) => {
// Make sure that repeated elements implement `Copy`.
let span = body.source_info(location).span;
let ty = operand.ty(body, tcx);
if !self.infcx.type_is_copy_modulo_regions(self.param_env, ty, span) {
let ccx = ConstCx::new_with_param_env(tcx, body, self.param_env);
let is_const_fn =
is_const_fn_in_array_repeat_expression(&ccx, &place, &body);
debug!("check_rvalue: is_const_fn={:?}", is_const_fn);
let def_id = body.source.def_id().expect_local();
self.infcx.report_selection_error(
&traits::Obligation::new(
ObligationCause::new(
span,
self.tcx().hir().local_def_id_to_hir_id(def_id),
traits::ObligationCauseCode::RepeatVec,
traits::ObligationCauseCode::RepeatVec(is_const_fn),
),
self.param_env,
ty::Binder::bind(ty::TraitRef::new(

View file

@ -18,6 +18,7 @@ use crate::borrow_check::type_check::{BorrowCheckContext, Locations};
/// variables, but not the type `b`.
pub(super) fn relate_types<'tcx>(
infcx: &InferCtxt<'_, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
a: Ty<'tcx>,
v: ty::Variance,
b: Ty<'tcx>,
@ -28,7 +29,7 @@ pub(super) fn relate_types<'tcx>(
debug!("relate_types(a={:?}, v={:?}, b={:?}, locations={:?})", a, v, b, locations);
TypeRelating::new(
infcx,
NllTypeRelatingDelegate::new(infcx, borrowck_context, locations, category),
NllTypeRelatingDelegate::new(infcx, borrowck_context, param_env, locations, category),
v,
)
.relate(a, b)?;
@ -39,6 +40,8 @@ struct NllTypeRelatingDelegate<'me, 'bccx, 'tcx> {
infcx: &'me InferCtxt<'me, 'tcx>,
borrowck_context: Option<&'me mut BorrowCheckContext<'bccx, 'tcx>>,
param_env: ty::ParamEnv<'tcx>,
/// Where (and why) is this relation taking place?
locations: Locations,
@ -50,14 +53,19 @@ impl NllTypeRelatingDelegate<'me, 'bccx, 'tcx> {
fn new(
infcx: &'me InferCtxt<'me, 'tcx>,
borrowck_context: Option<&'me mut BorrowCheckContext<'bccx, 'tcx>>,
param_env: ty::ParamEnv<'tcx>,
locations: Locations,
category: ConstraintCategory,
) -> Self {
Self { infcx, borrowck_context, locations, category }
Self { infcx, borrowck_context, param_env, locations, category }
}
}
impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> {
fn param_env(&self) -> ty::ParamEnv<'tcx> {
self.param_env
}
fn create_next_universe(&mut self) -> ty::UniverseIndex {
self.infcx.create_next_universe()
}

View file

@ -208,7 +208,7 @@ pub fn eval_to_const_value_raw_provider<'tcx>(
tcx: TyCtxt<'tcx>,
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
) -> ::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> {
// see comment in const_eval_raw_provider for what we're doing here
// see comment in eval_to_allocation_raw_provider for what we're doing here
if key.param_env.reveal() == Reveal::All {
let mut key = key;
key.param_env = key.param_env.with_user_facing();

View file

@ -21,7 +21,7 @@ use std::hash::Hash;
use super::{
CheckInAllocMsg, GlobalAlloc, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, OpTy,
ValueVisitor,
ScalarMaybeUninit, ValueVisitor,
};
macro_rules! throw_validation_failure {
@ -378,7 +378,11 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
value: OpTy<'tcx, M::PointerTag>,
kind: &str,
) -> InterpResult<'tcx> {
let value = self.ecx.read_immediate(value)?;
let value = try_validation!(
self.ecx.read_immediate(value),
self.path,
err_unsup!(ReadPointerAsBytes) => { "part of a pointer" } expected { "a proper pointer or integer value" },
);
// Handle wide pointers.
// Check metadata early, for better diagnostics
let place = try_validation!(
@ -485,6 +489,17 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
Ok(())
}
fn read_scalar(
&self,
op: OpTy<'tcx, M::PointerTag>,
) -> InterpResult<'tcx, ScalarMaybeUninit<M::PointerTag>> {
Ok(try_validation!(
self.ecx.read_scalar(op),
self.path,
err_unsup!(ReadPointerAsBytes) => { "(potentially part of) a pointer" } expected { "plain (non-pointer) bytes" },
))
}
/// Check if this is a value of primitive type, and if yes check the validity of the value
/// at that type. Return `true` if the type is indeed primitive.
fn try_visit_primitive(
@ -495,7 +510,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
let ty = value.layout.ty;
match ty.kind() {
ty::Bool => {
let value = self.ecx.read_scalar(value)?;
let value = self.read_scalar(value)?;
try_validation!(
value.to_bool(),
self.path,
@ -505,7 +520,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
Ok(true)
}
ty::Char => {
let value = self.ecx.read_scalar(value)?;
let value = self.read_scalar(value)?;
try_validation!(
value.to_char(),
self.path,
@ -515,11 +530,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
Ok(true)
}
ty::Float(_) | ty::Int(_) | ty::Uint(_) => {
let value = try_validation!(
self.ecx.read_scalar(value),
self.path,
err_unsup!(ReadPointerAsBytes) => { "read of part of a pointer" },
);
let value = self.read_scalar(value)?;
// NOTE: Keep this in sync with the array optimization for int/float
// types below!
if self.ctfe_mode.is_some() {
@ -541,9 +552,10 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
// actually enforce the strict rules for raw pointers (mostly because
// that lets us re-use `ref_to_mplace`).
let place = try_validation!(
self.ecx.ref_to_mplace(self.ecx.read_immediate(value)?),
self.ecx.read_immediate(value).and_then(|i| self.ecx.ref_to_mplace(i)),
self.path,
err_ub!(InvalidUninitBytes(None)) => { "uninitialized raw pointer" },
err_unsup!(ReadPointerAsBytes) => { "part of a pointer" } expected { "a proper pointer or integer value" },
);
if place.layout.is_unsized() {
self.check_wide_ptr_meta(place.meta, place.layout)?;
@ -569,9 +581,13 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
Ok(true)
}
ty::FnPtr(_sig) => {
let value = self.ecx.read_scalar(value)?;
let value = try_validation!(
self.ecx.read_immediate(value),
self.path,
err_unsup!(ReadPointerAsBytes) => { "part of a pointer" } expected { "a proper pointer or integer value" },
);
let _fn = try_validation!(
value.check_init().and_then(|ptr| self.ecx.memory.get_fn(ptr)),
value.to_scalar().and_then(|ptr| self.ecx.memory.get_fn(ptr)),
self.path,
err_ub!(DanglingIntPointer(..)) |
err_ub!(InvalidFunctionPointer(..)) |
@ -615,7 +631,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
op: OpTy<'tcx, M::PointerTag>,
scalar_layout: &Scalar,
) -> InterpResult<'tcx> {
let value = self.ecx.read_scalar(op)?;
let value = self.read_scalar(op)?;
let valid_range = &scalar_layout.valid_range;
let (lo, hi) = valid_range.clone().into_inner();
// Determine the allowed range

View file

@ -1231,3 +1231,38 @@ pub fn promote_candidates<'tcx>(
promotions
}
/// This function returns `true` if the function being called in the array
/// repeat expression is a `const` function.
crate fn is_const_fn_in_array_repeat_expression<'tcx>(
ccx: &ConstCx<'_, 'tcx>,
place: &Place<'tcx>,
body: &Body<'tcx>,
) -> bool {
match place.as_local() {
// rule out cases such as: `let my_var = some_fn(); [my_var; N]`
Some(local) if body.local_decls[local].is_user_variable() => return false,
None => return false,
_ => {}
}
for block in body.basic_blocks() {
if let Some(Terminator { kind: TerminatorKind::Call { func, destination, .. }, .. }) =
&block.terminator
{
if let Operand::Constant(box Constant { literal: ty::Const { ty, .. }, .. }) = func {
if let ty::FnDef(def_id, _) = *ty.kind() {
if let Some((destination_place, _)) = destination {
if destination_place == place {
if is_const_fn(ccx.tcx, def_id) {
return true;
}
}
}
}
}
}
}
false
}

View file

@ -510,11 +510,10 @@ impl Span {
/// items can be used (that is, a macro marked with
/// `#[allow_internal_unstable]`).
pub fn allows_unstable(&self, feature: Symbol) -> bool {
self.ctxt().outer_expn_data().allow_internal_unstable.map_or(false, |features| {
features
.iter()
.any(|&f| f == feature || f == sym::allow_internal_unstable_backcompat_hack)
})
self.ctxt()
.outer_expn_data()
.allow_internal_unstable
.map_or(false, |features| features.iter().any(|&f| f == feature))
}
/// Checks if this span arises from a compiler desugaring of kind `kind`.

View file

@ -252,7 +252,6 @@ symbols! {
allow_fail,
allow_internal_unsafe,
allow_internal_unstable,
allow_internal_unstable_backcompat_hack,
allowed,
always,
and,

View file

@ -1881,10 +1881,26 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
ObligationCauseCode::Coercion { source: _, target } => {
err.note(&format!("required by cast to type `{}`", self.ty_to_string(target)));
}
ObligationCauseCode::RepeatVec => {
ObligationCauseCode::RepeatVec(is_const_fn) => {
err.note(
"the `Copy` trait is required because the repeated element will be copied",
);
if is_const_fn {
err.help(
"consider creating a new `const` item and initializing with the result \
of the function call to be used in the repeat position, like \
`const VAL: Type = const_fn();` and `let x = [VAL; 42];`",
);
}
if self.tcx.sess.is_nightly_build() && is_const_fn {
err.help(
"create an inline `const` block, see PR \
#2920 <https://github.com/rust-lang/rfcs/pull/2920> \
for more information",
);
}
}
ObligationCauseCode::VariableType(hir_id) => {
let parent_node = self.tcx.hir().get_parent_node(hir_id);

View file

@ -10,6 +10,7 @@ use traits::{translate_substs, Reveal};
use tracing::debug;
#[instrument(level = "debug", skip(tcx))]
fn resolve_instance<'tcx>(
tcx: TyCtxt<'tcx>,
key: ty::ParamEnvAnd<'tcx, (DefId, SubstsRef<'tcx>)>,
@ -38,13 +39,13 @@ fn resolve_instance_of_const_arg<'tcx>(
)
}
#[instrument(level = "debug", skip(tcx))]
fn inner_resolve_instance<'tcx>(
tcx: TyCtxt<'tcx>,
key: ty::ParamEnvAnd<'tcx, (ty::WithOptConstParam<DefId>, SubstsRef<'tcx>)>,
) -> Result<Option<Instance<'tcx>>, ErrorReported> {
let (param_env, (def, substs)) = key.into_parts();
debug!("resolve(def={:?}, substs={:?})", def.did, substs);
let result = if let Some(trait_def_id) = tcx.trait_of_item(def.did) {
debug!(" => associated item, attempting to find impl in param_env {:#?}", param_env);
let item = tcx.associated_item(def.did);
@ -93,7 +94,7 @@ fn inner_resolve_instance<'tcx>(
};
Ok(Some(Instance { def, substs }))
};
debug!("resolve(def.did={:?}, substs={:?}) = {:?}", def.did, substs, result);
debug!("inner_resolve_instance: result={:?}", result);
result
}