Merge from rustc

This commit is contained in:
The Miri Cronjob Bot 2024-04-17 05:08:05 +00:00
commit e8739886f2
428 changed files with 4470 additions and 2615 deletions

View File

@ -210,9 +210,9 @@ dependencies = [
[[package]]
name = "ar_archive_writer"
version = "0.1.5"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9792d37ca5173d7e7f4fe453739a0671d0557915a030a383d6b866476bbc3e71"
checksum = "f0c269894b6fe5e9d7ada0cf69b5bf847ff35bc25fc271f08e1d080fce80339a"
dependencies = [
"object 0.32.2",
]
@ -3342,6 +3342,7 @@ name = "run_make_support"
version = "0.0.0"
dependencies = [
"object 0.34.0",
"regex",
"wasmparser",
]
@ -4278,6 +4279,7 @@ dependencies = [
"rustc_fluent_macro",
"rustc_graphviz",
"rustc_hir",
"rustc_hir_pretty",
"rustc_index",
"rustc_macros",
"rustc_query_system",

View File

@ -36,6 +36,7 @@ use rustc_macros::HashStable_Generic;
use rustc_span::source_map::{respan, Spanned};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP};
use std::cmp;
use std::fmt;
use std::mem;
use thin_vec::{thin_vec, ThinVec};
@ -63,7 +64,7 @@ impl fmt::Debug for Label {
/// A "Lifetime" is an annotation of the scope in which variable
/// can be used, e.g. `'a` in `&'a i32`.
#[derive(Clone, Encodable, Decodable, Copy, PartialEq, Eq)]
#[derive(Clone, Encodable, Decodable, Copy, PartialEq, Eq, Hash)]
pub struct Lifetime {
pub id: NodeId,
pub ident: Ident,
@ -731,6 +732,13 @@ impl BindingAnnotation {
Self::MUT_REF_MUT => "mut ref mut ",
}
}
pub fn cap_ref_mutability(mut self, mutbl: Mutability) -> Self {
if let ByRef::Yes(old_mutbl) = &mut self.0 {
*old_mutbl = cmp::min(*old_mutbl, mutbl);
}
self
}
}
#[derive(Clone, Encodable, Decodable, Debug)]
@ -2132,7 +2140,7 @@ pub enum TyKind {
/// The `NodeId` exists to prevent lowering from having to
/// generate `NodeId`s on the fly, which would complicate
/// the generation of opaque `type Foo = impl Trait` items significantly.
ImplTrait(NodeId, GenericBounds),
ImplTrait(NodeId, GenericBounds, Option<P<(ThinVec<PreciseCapturingArg>, Span)>>),
/// No-op; kept solely so that we can pretty-print faithfully.
Paren(P<Ty>),
/// Unused for now.
@ -2188,6 +2196,14 @@ pub enum TraitObjectSyntax {
None,
}
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum PreciseCapturingArg {
/// Lifetime parameter
Lifetime(Lifetime),
/// Type or const parameter
Arg(Path, NodeId),
}
/// Inline assembly operand explicit register or register class.
///
/// E.g., `"eax"` as in `asm!("mov eax, 2", out("eax") result)`.

View File

@ -308,11 +308,11 @@ impl MetaItem {
// FIXME: Share code with `parse_path`.
let path = match tokens.next().map(|tt| TokenTree::uninterpolate(tt)).as_deref() {
Some(&TokenTree::Token(
Token { kind: ref kind @ (token::Ident(..) | token::ModSep), span },
Token { kind: ref kind @ (token::Ident(..) | token::PathSep), span },
_,
)) => 'arm: {
let mut segments = if let &token::Ident(name, _) = kind {
if let Some(TokenTree::Token(Token { kind: token::ModSep, .. }, _)) =
if let Some(TokenTree::Token(Token { kind: token::PathSep, .. }, _)) =
tokens.peek()
{
tokens.next();
@ -331,7 +331,7 @@ impl MetaItem {
} else {
return None;
}
if let Some(TokenTree::Token(Token { kind: token::ModSep, .. }, _)) =
if let Some(TokenTree::Token(Token { kind: token::PathSep, .. }, _)) =
tokens.peek()
{
tokens.next();

View File

@ -259,6 +259,10 @@ pub trait MutVisitor: Sized {
noop_visit_param_bound(tpb, self);
}
fn visit_precise_capturing_arg(&mut self, arg: &mut PreciseCapturingArg) {
noop_visit_precise_capturing_arg(arg, self);
}
fn visit_mt(&mut self, mt: &mut MutTy) {
noop_visit_mt(mt, self);
}
@ -518,9 +522,14 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) {
TyKind::TraitObject(bounds, _syntax) => {
visit_vec(bounds, |bound| vis.visit_param_bound(bound))
}
TyKind::ImplTrait(id, bounds) => {
TyKind::ImplTrait(id, bounds, precise_capturing) => {
vis.visit_id(id);
visit_vec(bounds, |bound| vis.visit_param_bound(bound));
if let Some((precise_capturing, _span)) = precise_capturing.as_deref_mut() {
for arg in precise_capturing {
vis.visit_precise_capturing_arg(arg);
}
}
}
TyKind::MacCall(mac) => vis.visit_mac_call(mac),
TyKind::AnonStruct(id, fields) | TyKind::AnonUnion(id, fields) => {
@ -914,6 +923,18 @@ pub fn noop_visit_param_bound<T: MutVisitor>(pb: &mut GenericBound, vis: &mut T)
}
}
pub fn noop_visit_precise_capturing_arg<T: MutVisitor>(arg: &mut PreciseCapturingArg, vis: &mut T) {
match arg {
PreciseCapturingArg::Lifetime(lt) => {
vis.visit_lifetime(lt);
}
PreciseCapturingArg::Arg(path, id) => {
vis.visit_path(path);
vis.visit_id(id);
}
}
}
pub fn noop_flat_map_generic_param<T: MutVisitor>(
mut param: GenericParam,
vis: &mut T,

View File

@ -51,7 +51,7 @@ pub enum Delimiter {
Brace,
/// `[ ... ]`
Bracket,
/// `Ø ... Ø`
/// `∅ ... ∅`
/// An invisible delimiter, that may, for example, appear around tokens coming from a
/// "macro variable" `$var`. It is important to preserve operator priorities in cases like
/// `$var * 3` where `$var` is `1 + 2`.
@ -290,7 +290,7 @@ pub enum TokenKind {
/// `:`
Colon,
/// `::`
ModSep,
PathSep,
/// `->`
RArrow,
/// `<-`
@ -393,7 +393,7 @@ impl TokenKind {
BinOpEq(Shr) => (Gt, Ge),
DotDot => (Dot, Dot),
DotDotDot => (Dot, DotDot),
ModSep => (Colon, Colon),
PathSep => (Colon, Colon),
RArrow => (BinOp(Minus), Gt),
LArrow => (Lt, BinOp(Minus)),
FatArrow => (Eq, Gt),
@ -454,7 +454,9 @@ impl Token {
match self.kind {
Eq | Lt | Le | EqEq | Ne | Ge | Gt | AndAnd | OrOr | Not | Tilde | BinOp(_)
| BinOpEq(_) | At | Dot | DotDot | DotDotDot | DotDotEq | Comma | Semi | Colon
| ModSep | RArrow | LArrow | FatArrow | Pound | Dollar | Question | SingleQuote => true,
| PathSep | RArrow | LArrow | FatArrow | Pound | Dollar | Question | SingleQuote => {
true
}
OpenDelim(..) | CloseDelim(..) | Literal(..) | DocComment(..) | Ident(..)
| Lifetime(..) | Interpolated(..) | Eof => false,
@ -481,7 +483,7 @@ impl Token {
// DotDotDot is no longer supported, but we need some way to display the error
DotDot | DotDotDot | DotDotEq | // range notation
Lt | BinOp(Shl) | // associated path
ModSep | // global path
PathSep | // global path
Lifetime(..) | // labeled loop
Pound => true, // expression attributes
Interpolated(ref nt) => matches!(&nt.0, NtLiteral(..) |
@ -507,7 +509,7 @@ impl Token {
// DotDotDot is no longer supported
| DotDot | DotDotDot | DotDotEq // ranges
| Lt | BinOp(Shl) // associated path
| ModSep => true, // global path
| PathSep => true, // global path
Interpolated(ref nt) => matches!(&nt.0, NtLiteral(..) |
NtPat(..) |
NtBlock(..) |
@ -530,7 +532,7 @@ impl Token {
Question | // maybe bound in trait object
Lifetime(..) | // lifetime bound in trait object
Lt | BinOp(Shl) | // associated path
ModSep => true, // global path
PathSep => true, // global path
Interpolated(ref nt) => matches!(&nt.0, NtTy(..) | NtPath(..)),
// For anonymous structs or unions, which only appear in specific positions
// (type of struct fields or union fields), we don't consider them as regular types
@ -708,7 +710,7 @@ impl Token {
}
pub fn is_path_start(&self) -> bool {
self == &ModSep
self == &PathSep
|| self.is_qpath_start()
|| self.is_whole_path()
|| self.is_path_segment_keyword()
@ -821,7 +823,7 @@ impl Token {
_ => return None,
},
Colon => match joint.kind {
Colon => ModSep,
Colon => PathSep,
_ => return None,
},
SingleQuote => match joint.kind {
@ -830,7 +832,7 @@ impl Token {
},
Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | BinOpEq(..) | At | DotDotDot
| DotDotEq | Comma | Semi | ModSep | RArrow | LArrow | FatArrow | Pound | Dollar
| DotDotEq | Comma | Semi | PathSep | RArrow | LArrow | FatArrow | Pound | Dollar
| Question | OpenDelim(..) | CloseDelim(..) | Literal(..) | Ident(..)
| Lifetime(..) | Interpolated(..) | DocComment(..) | Eof => return None,
};

View File

@ -184,6 +184,9 @@ pub trait Visitor<'ast>: Sized {
fn visit_param_bound(&mut self, bounds: &'ast GenericBound, _ctxt: BoundKind) -> Self::Result {
walk_param_bound(self, bounds)
}
fn visit_precise_capturing_arg(&mut self, arg: &'ast PreciseCapturingArg) {
walk_precise_capturing_arg(self, arg);
}
fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef) -> Self::Result {
walk_poly_trait_ref(self, t)
}
@ -457,8 +460,13 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) -> V::Result {
TyKind::TraitObject(bounds, ..) => {
walk_list!(visitor, visit_param_bound, bounds, BoundKind::TraitObject);
}
TyKind::ImplTrait(_, bounds) => {
TyKind::ImplTrait(_, bounds, precise_capturing) => {
walk_list!(visitor, visit_param_bound, bounds, BoundKind::Impl);
if let Some((precise_capturing, _span)) = precise_capturing.as_deref() {
for arg in precise_capturing {
try_visit!(visitor.visit_precise_capturing_arg(arg));
}
}
}
TyKind::Typeof(expression) => try_visit!(visitor.visit_anon_const(expression)),
TyKind::Infer | TyKind::ImplicitSelf | TyKind::Dummy | TyKind::Err(_) => {}
@ -637,6 +645,20 @@ pub fn walk_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a GenericB
}
}
pub fn walk_precise_capturing_arg<'a, V: Visitor<'a>>(
visitor: &mut V,
arg: &'a PreciseCapturingArg,
) {
match arg {
PreciseCapturingArg::Lifetime(lt) => {
visitor.visit_lifetime(lt, LifetimeCtxt::GenericArg);
}
PreciseCapturingArg::Arg(path, id) => {
visitor.visit_path(path, *id);
}
}
}
pub fn walk_generic_param<'a, V: Visitor<'a>>(
visitor: &mut V,
param: &'a GenericParam,

View File

@ -127,6 +127,8 @@ ast_lowering_never_pattern_with_guard =
a guard on a never pattern will never be run
.suggestion = remove this guard
ast_lowering_no_precise_captures_on_apit = `use<...>` precise capturing syntax not allowed on argument-position `impl Trait`
ast_lowering_previously_used_here = previously used here
ast_lowering_register1 = register `{$reg1_name}`

View File

@ -414,3 +414,10 @@ pub(crate) struct AsyncBoundOnlyForFnTraits {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(ast_lowering_no_precise_captures_on_apit)]
pub(crate) struct NoPreciseCapturesOnApit {
#[primary_span]
pub span: Span,
}

View File

@ -14,6 +14,7 @@ use rustc_ast::*;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::HirId;
use rustc_middle::span_bug;
use rustc_session::errors::report_lit_error;
use rustc_span::source_map::{respan, Spanned};
@ -701,8 +702,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
pub(super) fn maybe_forward_track_caller(
&mut self,
span: Span,
outer_hir_id: hir::HirId,
inner_hir_id: hir::HirId,
outer_hir_id: HirId,
inner_hir_id: HirId,
) {
if self.tcx.features().async_fn_track_caller
&& let Some(attrs) = self.attrs.get(&outer_hir_id.local_id)
@ -1048,7 +1049,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
binder: &ClosureBinder,
capture_clause: CaptureBy,
closure_id: NodeId,
closure_hir_id: hir::HirId,
closure_hir_id: HirId,
coroutine_kind: CoroutineKind,
decl: &FnDecl,
body: &Expr,
@ -2036,7 +2037,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
&mut self,
sp: Span,
ident: Ident,
binding: hir::HirId,
binding: HirId,
) -> &'hir hir::Expr<'hir> {
self.arena.alloc(self.expr_ident_mut(sp, ident, binding))
}
@ -2045,7 +2046,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
&mut self,
span: Span,
ident: Ident,
binding: hir::HirId,
binding: HirId,
) -> hir::Expr<'hir> {
let hir_id = self.next_id();
let res = Res::Local(binding);

View File

@ -385,4 +385,21 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
fn visit_pattern_type_pattern(&mut self, p: &'hir hir::Pat<'hir>) {
self.visit_pat(p)
}
fn visit_precise_capturing_arg(
&mut self,
arg: &'hir PreciseCapturingArg<'hir>,
) -> Self::Result {
match arg {
PreciseCapturingArg::Lifetime(_) => {
// This is represented as a `Node::Lifetime`, intravisit will get to it below.
}
PreciseCapturingArg::Param(param) => self.insert(
param.ident.span,
param.hir_id,
Node::PreciseCapturingNonLifetimeArg(param),
),
}
intravisit::walk_precise_capturing_arg(self, arg);
}
}

View File

@ -48,6 +48,7 @@ use rustc_ast::{self as ast, *};
use rustc_ast_pretty::pprust;
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::FxIndexSet;
use rustc_data_structures::sorted_map::SortedMap;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::Lrc;
@ -56,7 +57,7 @@ use rustc_hir as hir;
use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
use rustc_hir::def_id::{LocalDefId, LocalDefIdMap, CRATE_DEF_ID, LOCAL_CRATE};
use rustc_hir::{
ConstArg, GenericArg, ItemLocalMap, MissingLifetimeKind, ParamName, TraitCandidate,
ConstArg, GenericArg, HirId, ItemLocalMap, MissingLifetimeKind, ParamName, TraitCandidate,
};
use rustc_index::{Idx, IndexSlice, IndexVec};
use rustc_macros::extension;
@ -107,7 +108,7 @@ struct LoweringContext<'a, 'hir> {
/// When inside an `async` context, this is the `HirId` of the
/// `task_context` local bound to the resume argument of the coroutine.
task_context: Option<hir::HirId>,
task_context: Option<HirId>,
/// Used to get the current `fn`'s def span to point to when using `await`
/// outside of an `async fn`.
@ -661,18 +662,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
/// `HirIdValidator` later on, which makes sure that all `NodeId`s got mapped
/// properly. Calling the method twice with the same `NodeId` is fine though.
#[instrument(level = "debug", skip(self), ret)]
fn lower_node_id(&mut self, ast_node_id: NodeId) -> hir::HirId {
fn lower_node_id(&mut self, ast_node_id: NodeId) -> HirId {
assert_ne!(ast_node_id, DUMMY_NODE_ID);
match self.node_id_to_local_id.entry(ast_node_id) {
Entry::Occupied(o) => {
hir::HirId { owner: self.current_hir_id_owner, local_id: *o.get() }
}
Entry::Occupied(o) => HirId { owner: self.current_hir_id_owner, local_id: *o.get() },
Entry::Vacant(v) => {
// Generate a new `HirId`.
let owner = self.current_hir_id_owner;
let local_id = self.item_local_id_counter;
let hir_id = hir::HirId { owner, local_id };
let hir_id = HirId { owner, local_id };
v.insert(local_id);
self.item_local_id_counter.increment_by(1);
@ -693,12 +692,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
/// Generate a new `HirId` without a backing `NodeId`.
#[instrument(level = "debug", skip(self), ret)]
fn next_id(&mut self) -> hir::HirId {
fn next_id(&mut self) -> HirId {
let owner = self.current_hir_id_owner;
let local_id = self.item_local_id_counter;
assert_ne!(local_id, hir::ItemLocalId::ZERO);
self.item_local_id_counter.increment_by(1);
hir::HirId { owner, local_id }
HirId { owner, local_id }
}
#[instrument(level = "trace", skip(self))]
@ -706,7 +705,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let res: Result<Res, ()> = res.apply_id(|id| {
let owner = self.current_hir_id_owner;
let local_id = self.node_id_to_local_id.get(&id).copied().ok_or(())?;
Ok(hir::HirId { owner, local_id })
Ok(HirId { owner, local_id })
});
trace!(?res);
@ -889,7 +888,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
ret
}
fn lower_attrs(&mut self, id: hir::HirId, attrs: &[Attribute]) -> Option<&'hir [Attribute]> {
fn lower_attrs(&mut self, id: HirId, attrs: &[Attribute]) -> Option<&'hir [Attribute]> {
if attrs.is_empty() {
None
} else {
@ -921,7 +920,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
Attribute { kind, id: attr.id, style: attr.style, span: self.lower_span(attr.span) }
}
fn alias_attrs(&mut self, id: hir::HirId, target_id: hir::HirId) {
fn alias_attrs(&mut self, id: HirId, target_id: HirId) {
debug_assert_eq!(id.owner, self.current_hir_id_owner);
debug_assert_eq!(target_id.owner, self.current_hir_id_owner);
if let Some(&a) = self.attrs.get(&target_id.local_id) {
@ -1398,7 +1397,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
});
hir::TyKind::TraitObject(bounds, lifetime_bound, *kind)
}
TyKind::ImplTrait(def_node_id, bounds) => {
TyKind::ImplTrait(def_node_id, bounds, precise_capturing) => {
let span = t.span;
match itctx {
ImplTraitContext::OpaqueTy { origin, fn_kind } => self.lower_opaque_impl_trait(
@ -1408,8 +1407,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
bounds,
fn_kind,
itctx,
precise_capturing.as_deref().map(|(args, _)| args.as_slice()),
),
ImplTraitContext::Universal => {
if let Some(&(_, span)) = precise_capturing.as_deref() {
self.tcx.dcx().emit_err(errors::NoPreciseCapturesOnApit { span });
};
let span = t.span;
// HACK: pprust breaks strings with newlines when the type
@ -1520,6 +1523,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
bounds: &GenericBounds,
fn_kind: Option<FnDeclKind>,
itctx: ImplTraitContext,
precise_capturing_args: Option<&[PreciseCapturingArg]>,
) -> hir::TyKind<'hir> {
// Make sure we know that some funky desugaring has been going on here.
// This is a first: there is code in other places like for loop
@ -1528,42 +1532,59 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// frequently opened issues show.
let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None);
let captured_lifetimes_to_duplicate = match origin {
hir::OpaqueTyOrigin::TyAlias { .. } => {
// type alias impl trait and associated type position impl trait were
// decided to capture all in-scope lifetimes, which we collect for
// all opaques during resolution.
self.resolver
.take_extra_lifetime_params(opaque_ty_node_id)
.into_iter()
.map(|(ident, id, _)| Lifetime { id, ident })
let captured_lifetimes_to_duplicate =
if let Some(precise_capturing) = precise_capturing_args {
// We'll actually validate these later on; all we need is the list of
// lifetimes to duplicate during this portion of lowering.
precise_capturing
.iter()
.filter_map(|arg| match arg {
PreciseCapturingArg::Lifetime(lt) => Some(*lt),
PreciseCapturingArg::Arg(..) => None,
})
// Add in all the lifetimes mentioned in the bounds. We will error
// them out later, but capturing them here is important to make sure
// they actually get resolved in resolve_bound_vars.
.chain(lifetime_collector::lifetimes_in_bounds(self.resolver, bounds))
.collect()
}
hir::OpaqueTyOrigin::FnReturn(..) => {
if matches!(
fn_kind.expect("expected RPITs to be lowered with a FnKind"),
FnDeclKind::Impl | FnDeclKind::Trait
) || self.tcx.features().lifetime_capture_rules_2024
|| span.at_least_rust_2024()
{
// return-position impl trait in trait was decided to capture all
// in-scope lifetimes, which we collect for all opaques during resolution.
self.resolver
.take_extra_lifetime_params(opaque_ty_node_id)
.into_iter()
.map(|(ident, id, _)| Lifetime { id, ident })
.collect()
} else {
// in fn return position, like the `fn test<'a>() -> impl Debug + 'a`
// example, we only need to duplicate lifetimes that appear in the
// bounds, since those are the only ones that are captured by the opaque.
lifetime_collector::lifetimes_in_bounds(self.resolver, bounds)
} else {
match origin {
hir::OpaqueTyOrigin::TyAlias { .. } => {
// type alias impl trait and associated type position impl trait were
// decided to capture all in-scope lifetimes, which we collect for
// all opaques during resolution.
self.resolver
.take_extra_lifetime_params(opaque_ty_node_id)
.into_iter()
.map(|(ident, id, _)| Lifetime { id, ident })
.collect()
}
hir::OpaqueTyOrigin::FnReturn(..) => {
if matches!(
fn_kind.expect("expected RPITs to be lowered with a FnKind"),
FnDeclKind::Impl | FnDeclKind::Trait
) || self.tcx.features().lifetime_capture_rules_2024
|| span.at_least_rust_2024()
{
// return-position impl trait in trait was decided to capture all
// in-scope lifetimes, which we collect for all opaques during resolution.
self.resolver
.take_extra_lifetime_params(opaque_ty_node_id)
.into_iter()
.map(|(ident, id, _)| Lifetime { id, ident })
.collect()
} else {
// in fn return position, like the `fn test<'a>() -> impl Debug + 'a`
// example, we only need to duplicate lifetimes that appear in the
// bounds, since those are the only ones that are captured by the opaque.
lifetime_collector::lifetimes_in_bounds(self.resolver, bounds)
}
}
hir::OpaqueTyOrigin::AsyncFn(..) => {
unreachable!("should be using `lower_async_fn_ret_ty`")
}
}
}
hir::OpaqueTyOrigin::AsyncFn(..) => {
unreachable!("should be using `lower_async_fn_ret_ty`")
}
};
};
debug!(?captured_lifetimes_to_duplicate);
self.lower_opaque_inner(
@ -1573,6 +1594,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
captured_lifetimes_to_duplicate,
span,
opaque_ty_span,
precise_capturing_args,
|this| this.lower_param_bounds(bounds, itctx),
)
}
@ -1582,9 +1604,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
opaque_ty_node_id: NodeId,
origin: hir::OpaqueTyOrigin,
in_trait: bool,
captured_lifetimes_to_duplicate: Vec<Lifetime>,
captured_lifetimes_to_duplicate: FxIndexSet<Lifetime>,
span: Span,
opaque_ty_span: Span,
precise_capturing_args: Option<&[PreciseCapturingArg]>,
lower_item_bounds: impl FnOnce(&mut Self) -> &'hir [hir::GenericBound<'hir>],
) -> hir::TyKind<'hir> {
let opaque_ty_def_id = self.create_def(
@ -1671,8 +1694,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// Install the remapping from old to new (if any). This makes sure that
// any lifetimes that would have resolved to the def-id of captured
// lifetimes are remapped to the new *synthetic* lifetimes of the opaque.
let bounds = this
.with_remapping(captured_to_synthesized_mapping, |this| lower_item_bounds(this));
let (bounds, precise_capturing_args) =
this.with_remapping(captured_to_synthesized_mapping, |this| {
(
lower_item_bounds(this),
precise_capturing_args.map(|precise_capturing| {
this.lower_precise_capturing_args(precise_capturing)
}),
)
});
let generic_params =
this.arena.alloc_from_iter(synthesized_lifetime_definitions.iter().map(
@ -1717,6 +1747,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
origin,
lifetime_mapping,
in_trait,
precise_capturing_args,
};
// Generate an `type Foo = impl Trait;` declaration.
@ -1749,6 +1780,30 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
)
}
fn lower_precise_capturing_args(
&mut self,
precise_capturing_args: &[PreciseCapturingArg],
) -> &'hir [hir::PreciseCapturingArg<'hir>] {
self.arena.alloc_from_iter(precise_capturing_args.iter().map(|arg| match arg {
PreciseCapturingArg::Lifetime(lt) => {
hir::PreciseCapturingArg::Lifetime(self.lower_lifetime(lt))
}
PreciseCapturingArg::Arg(path, id) => {
let [segment] = path.segments.as_slice() else {
panic!();
};
let res = self.resolver.get_partial_res(*id).map_or(Res::Err, |partial_res| {
partial_res.full_res().expect("no partial res expected for precise capture arg")
});
hir::PreciseCapturingArg::Param(hir::PreciseCapturingNonLifetimeArg {
hir_id: self.lower_node_id(*id),
ident: self.lower_ident(segment.ident),
res: self.lower_res(res),
})
}
}))
}
fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Ident] {
self.arena.alloc_from_iter(decl.inputs.iter().map(|param| match param.pat.kind {
PatKind::Ident(_, ident, _) => self.lower_ident(ident),
@ -1889,7 +1944,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let opaque_ty_span =
self.mark_span_with_reason(DesugaringKind::Async, span, allowed_features);
let captured_lifetimes: Vec<_> = self
let captured_lifetimes = self
.resolver
.take_extra_lifetime_params(opaque_ty_node_id)
.into_iter()
@ -1903,6 +1958,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
captured_lifetimes,
span,
opaque_ty_span,
None,
|this| {
let bound = this.lower_coroutine_fn_output_type_to_bound(
output,
@ -2421,11 +2477,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.pat(span, hir::PatKind::Struct(qpath, fields, false))
}
fn pat_ident(&mut self, span: Span, ident: Ident) -> (&'hir hir::Pat<'hir>, hir::HirId) {
fn pat_ident(&mut self, span: Span, ident: Ident) -> (&'hir hir::Pat<'hir>, HirId) {
self.pat_ident_binding_mode(span, ident, hir::BindingAnnotation::NONE)
}
fn pat_ident_mut(&mut self, span: Span, ident: Ident) -> (hir::Pat<'hir>, hir::HirId) {
fn pat_ident_mut(&mut self, span: Span, ident: Ident) -> (hir::Pat<'hir>, HirId) {
self.pat_ident_binding_mode_mut(span, ident, hir::BindingAnnotation::NONE)
}
@ -2434,7 +2490,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
span: Span,
ident: Ident,
bm: hir::BindingAnnotation,
) -> (&'hir hir::Pat<'hir>, hir::HirId) {
) -> (&'hir hir::Pat<'hir>, HirId) {
let (pat, hir_id) = self.pat_ident_binding_mode_mut(span, ident, bm);
(self.arena.alloc(pat), hir_id)
}
@ -2444,7 +2500,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
span: Span,
ident: Ident,
bm: hir::BindingAnnotation,
) -> (hir::Pat<'hir>, hir::HirId) {
) -> (hir::Pat<'hir>, HirId) {
let hir_id = self.next_id();
(
@ -2476,12 +2532,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
}
fn ty_path(
&mut self,
mut hir_id: hir::HirId,
span: Span,
qpath: hir::QPath<'hir>,
) -> hir::Ty<'hir> {
fn ty_path(&mut self, mut hir_id: HirId, span: Span, qpath: hir::QPath<'hir>) -> hir::Ty<'hir> {
let kind = match qpath {
hir::QPath::Resolved(None, path) => {
// Turn trait object paths into `TyKind::TraitObject` instead.

View File

@ -1,6 +1,7 @@
use super::ResolverAstLoweringExt;
use rustc_ast::visit::{self, BoundKind, LifetimeCtxt, Visitor};
use rustc_ast::{GenericBounds, Lifetime, NodeId, PathSegment, PolyTraitRef, Ty, TyKind};
use rustc_data_structures::fx::FxIndexSet;
use rustc_hir::def::{DefKind, LifetimeRes, Res};
use rustc_middle::span_bug;
use rustc_middle::ty::ResolverAstLowering;
@ -10,27 +11,23 @@ use rustc_span::Span;
struct LifetimeCollectVisitor<'ast> {
resolver: &'ast ResolverAstLowering,
current_binders: Vec<NodeId>,
collected_lifetimes: Vec<Lifetime>,
collected_lifetimes: FxIndexSet<Lifetime>,
}
impl<'ast> LifetimeCollectVisitor<'ast> {
fn new(resolver: &'ast ResolverAstLowering) -> Self {
Self { resolver, current_binders: Vec::new(), collected_lifetimes: Vec::new() }
Self { resolver, current_binders: Vec::new(), collected_lifetimes: FxIndexSet::default() }
}
fn record_lifetime_use(&mut self, lifetime: Lifetime) {
match self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error) {
LifetimeRes::Param { binder, .. } | LifetimeRes::Fresh { binder, .. } => {
if !self.current_binders.contains(&binder) {
if !self.collected_lifetimes.contains(&lifetime) {
self.collected_lifetimes.push(lifetime);
}
self.collected_lifetimes.insert(lifetime);
}
}
LifetimeRes::Static | LifetimeRes::Error => {
if !self.collected_lifetimes.contains(&lifetime) {
self.collected_lifetimes.push(lifetime);
}
self.collected_lifetimes.insert(lifetime);
}
LifetimeRes::Infer => {}
res => {
@ -111,7 +108,7 @@ impl<'ast> Visitor<'ast> for LifetimeCollectVisitor<'ast> {
pub(crate) fn lifetimes_in_bounds(
resolver: &ResolverAstLowering,
bounds: &GenericBounds,
) -> Vec<Lifetime> {
) -> FxIndexSet<Lifetime> {
let mut visitor = LifetimeCollectVisitor::new(resolver);
for bound in bounds {
visitor.visit_param_bound(bound, BoundKind::Bound);

View File

@ -737,7 +737,7 @@ impl<'a> AstValidator<'a> {
}
}
}
TyKind::ImplTrait(_, bounds) => {
TyKind::ImplTrait(_, bounds, _) => {
if self.is_impl_trait_banned {
self.dcx().emit_err(errors::ImplTraitPath { span: ty.span });
}

View File

@ -569,6 +569,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
gate_all!(fn_delegation, "functions delegation is not yet fully implemented");
gate_all!(postfix_match, "postfix match is experimental");
gate_all!(mut_ref, "mutable by-reference bindings are experimental");
gate_all!(precise_capturing, "precise captures on `impl Trait` are experimental");
if !visitor.features.never_patterns {
if let Some(spans) = spans.get(&sym::never_patterns) {

View File

@ -893,7 +893,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
token::Comma => ",".into(),
token::Semi => ";".into(),
token::Colon => ":".into(),
token::ModSep => "::".into(),
token::PathSep => "::".into(),
token::RArrow => "->".into(),
token::LArrow => "<-".into(),
token::FatArrow => "=>".into(),
@ -1150,8 +1150,17 @@ impl<'a> State<'a> {
}
self.print_type_bounds(bounds);
}
ast::TyKind::ImplTrait(_, bounds) => {
ast::TyKind::ImplTrait(_, bounds, precise_capturing_args) => {
self.word_nbsp("impl");
if let Some((precise_capturing_args, ..)) = precise_capturing_args.as_deref() {
self.word("use");
self.word("<");
self.commasep(Inconsistent, precise_capturing_args, |s, arg| match arg {
ast::PreciseCapturingArg::Arg(p, _) => s.print_path(p, false, 0),
ast::PreciseCapturingArg::Lifetime(lt) => s.print_lifetime(*lt),
});
self.word(">")
}
self.print_type_bounds(bounds);
}
ast::TyKind::Array(ty, length) => {

View File

@ -3,6 +3,7 @@ use super::*;
use rustc_ast as ast;
use rustc_span::create_default_session_globals_then;
use rustc_span::symbol::Ident;
use rustc_span::DUMMY_SP;
use thin_vec::ThinVec;
fn fun_to_string(
@ -28,10 +29,7 @@ fn test_fun_to_string() {
create_default_session_globals_then(|| {
let abba_ident = Ident::from_str("abba");
let decl = ast::FnDecl {
inputs: ThinVec::new(),
output: ast::FnRetTy::Default(rustc_span::DUMMY_SP),
};
let decl = ast::FnDecl { inputs: ThinVec::new(), output: ast::FnRetTy::Default(DUMMY_SP) };
let generics = ast::Generics::default();
assert_eq!(
fun_to_string(&decl, ast::FnHeader::default(), abba_ident, &generics),
@ -48,7 +46,7 @@ fn test_variant_to_string() {
let var = ast::Variant {
ident,
vis: ast::Visibility {
span: rustc_span::DUMMY_SP,
span: DUMMY_SP,
kind: ast::VisibilityKind::Inherited,
tokens: None,
},
@ -56,7 +54,7 @@ fn test_variant_to_string() {
id: ast::DUMMY_NODE_ID,
data: ast::VariantData::Unit(ast::DUMMY_NODE_ID),
disr_expr: None,
span: rustc_span::DUMMY_SP,
span: DUMMY_SP,
is_placeholder: false,
};

View File

@ -1752,32 +1752,31 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let tcx = self.infcx.tcx;
let hir = tcx.hir();
let Some(body_id) = tcx.hir_node(self.mir_hir_id()).body_id() else { return };
struct FindUselessClone<'hir> {
tcx: TyCtxt<'hir>,
def_id: DefId,
pub clones: Vec<&'hir hir::Expr<'hir>>,
struct FindUselessClone<'tcx> {
tcx: TyCtxt<'tcx>,
typeck_results: &'tcx ty::TypeckResults<'tcx>,
pub clones: Vec<&'tcx hir::Expr<'tcx>>,
}
impl<'hir> FindUselessClone<'hir> {
pub fn new(tcx: TyCtxt<'hir>, def_id: DefId) -> Self {
Self { tcx, def_id, clones: vec![] }
impl<'tcx> FindUselessClone<'tcx> {
pub fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
Self { tcx, typeck_results: tcx.typeck(def_id), clones: vec![] }
}
}
impl<'v> Visitor<'v> for FindUselessClone<'v> {
fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
if let hir::ExprKind::MethodCall(segment, _rcvr, args, _span) = ex.kind
&& segment.ident.name == sym::clone
&& args.len() == 0
&& let Some(def_id) = self.def_id.as_local()
&& let Some(method) = self.tcx.lookup_method_for_diagnostic((def_id, ex.hir_id))
&& Some(self.tcx.parent(method)) == self.tcx.lang_items().clone_trait()
impl<'tcx> Visitor<'tcx> for FindUselessClone<'tcx> {
fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
if let hir::ExprKind::MethodCall(..) = ex.kind
&& let Some(method_def_id) =
self.typeck_results.type_dependent_def_id(ex.hir_id)
&& self.tcx.lang_items().clone_trait() == Some(self.tcx.parent(method_def_id))
{
self.clones.push(ex);
}
hir::intravisit::walk_expr(self, ex);
}
}
let mut expr_finder = FindUselessClone::new(tcx, self.mir_def_id().into());
let mut expr_finder = FindUselessClone::new(tcx, self.mir_def_id());
let body = hir.body(body_id).value;
expr_finder.visit_expr(body);

View File

@ -26,7 +26,6 @@ use rustc_middle::ty::{self, RegionVid, Ty};
use rustc_middle::ty::{Region, TyCtxt};
use rustc_span::symbol::{kw, Ident};
use rustc_span::Span;
use rustc_trait_selection::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::{Obligation, ObligationCtxt};
@ -813,7 +812,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
self.add_static_impl_trait_suggestion(&mut diag, *fr, fr_name, *outlived_fr);
self.suggest_adding_lifetime_params(&mut diag, *fr, *outlived_fr);
self.suggest_move_on_borrowing_closure(&mut diag);
self.suggest_deref_closure_value(&mut diag);
self.suggest_deref_closure_return(&mut diag);
diag
}
@ -1048,125 +1047,111 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
/// When encountering a lifetime error caused by the return type of a closure, check the
/// corresponding trait bound and see if dereferencing the closure return value would satisfy
/// them. If so, we produce a structured suggestion.
fn suggest_deref_closure_value(&self, diag: &mut Diag<'_>) {
fn suggest_deref_closure_return(&self, diag: &mut Diag<'_>) {
let tcx = self.infcx.tcx;
let map = tcx.hir();
// Get the closure return value and type.
let body_id = map.body_owned_by(self.mir_def_id());
let body = &map.body(body_id);
let value = &body.value.peel_blocks();
let hir::Node::Expr(closure_expr) = tcx.hir_node_by_def_id(self.mir_def_id()) else {
let closure_def_id = self.mir_def_id();
let hir::Node::Expr(
closure_expr @ hir::Expr {
kind: hir::ExprKind::Closure(hir::Closure { body, .. }), ..
},
) = tcx.hir_node_by_def_id(closure_def_id)
else {
return;
};
let fn_call_id = tcx.parent_hir_id(self.mir_hir_id());
let hir::Node::Expr(expr) = tcx.hir_node(fn_call_id) else { return };
let def_id = map.enclosing_body_owner(fn_call_id);
let tables = tcx.typeck(def_id);
let Some(return_value_ty) = tables.node_type_opt(value.hir_id) else { return };
let return_value_ty = self.infcx.resolve_vars_if_possible(return_value_ty);
let ty::Closure(_, args) = *tcx.type_of(closure_def_id).instantiate_identity().kind()
else {
return;
};
let args = args.as_closure();
// Make sure that the parent expression is a method call.
let parent_expr_id = tcx.parent_hir_id(self.mir_hir_id());
let hir::Node::Expr(
parent_expr @ hir::Expr {
kind: hir::ExprKind::MethodCall(_, rcvr, call_args, _), ..
},
) = tcx.hir_node(parent_expr_id)
else {
return;
};
let typeck_results = tcx.typeck(self.mir_def_id());
// We don't use `ty.peel_refs()` to get the number of `*`s needed to get the root type.
let mut ty = return_value_ty;
let liberated_sig = tcx.liberate_late_bound_regions(closure_def_id.to_def_id(), args.sig());
let mut peeled_ty = liberated_sig.output();
let mut count = 0;
while let ty::Ref(_, t, _) = ty.kind() {
ty = *t;
while let ty::Ref(_, ref_ty, _) = *peeled_ty.kind() {
peeled_ty = ref_ty;
count += 1;
}
if !self.infcx.type_is_copy_modulo_regions(self.param_env, ty) {
if !self.infcx.type_is_copy_modulo_regions(self.param_env, peeled_ty) {
return;
}
// Build a new closure where the return type is an owned value, instead of a ref.
let Some(ty::Closure(did, args)) =
tables.node_type_opt(closure_expr.hir_id).as_ref().map(|ty| ty.kind())
else {
return;
};
let sig = args.as_closure().sig();
let closure_sig_as_fn_ptr_ty = Ty::new_fn_ptr(
tcx,
sig.map_bound(|s| {
let unsafety = hir::Unsafety::Normal;
use rustc_target::spec::abi;
tcx.mk_fn_sig(
[s.inputs()[0]],
s.output().peel_refs(),
s.c_variadic,
unsafety,
abi::Abi::Rust,
)
}),
ty::Binder::dummy(tcx.mk_fn_sig(
liberated_sig.inputs().iter().copied(),
peeled_ty,
liberated_sig.c_variadic,
hir::Unsafety::Normal,
rustc_target::spec::abi::Abi::Rust,
)),
);
let parent_args = GenericArgs::identity_for_item(
let closure_ty = Ty::new_closure(
tcx,
tcx.typeck_root_def_id(self.mir_def_id().to_def_id()),
closure_def_id.to_def_id(),
ty::ClosureArgs::new(
tcx,
ty::ClosureArgsParts {
parent_args: args.parent_args(),
closure_kind_ty: args.kind_ty(),
tupled_upvars_ty: args.tupled_upvars_ty(),
closure_sig_as_fn_ptr_ty,
},
)
.args,
);
let closure_kind = args.as_closure().kind();
let closure_kind_ty = Ty::from_closure_kind(tcx, closure_kind);
let tupled_upvars_ty = self.infcx.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::ClosureSynthetic,
span: closure_expr.span,
});
let closure_args = ty::ClosureArgs::new(
tcx,
ty::ClosureArgsParts {
parent_args,
closure_kind_ty,
closure_sig_as_fn_ptr_ty,
tupled_upvars_ty,
},
);
let closure_ty = Ty::new_closure(tcx, *did, closure_args.args);
let closure_ty = tcx.erase_regions(closure_ty);
let hir::ExprKind::MethodCall(_, rcvr, args, _) = expr.kind else { return };
let Some(pos) = args
.iter()
.enumerate()
.find(|(_, arg)| arg.hir_id == closure_expr.hir_id)
.map(|(i, _)| i)
let Some((closure_arg_pos, _)) =
call_args.iter().enumerate().find(|(_, arg)| arg.hir_id == closure_expr.hir_id)
else {
return;
};
// The found `Self` type of the method call.
let Some(possible_rcvr_ty) = tables.node_type_opt(rcvr.hir_id) else { return };
// The `MethodCall` expression is `Res::Err`, so we search for the method on the `rcvr_ty`.
let Some(method) = tcx.lookup_method_for_diagnostic((self.mir_def_id(), expr.hir_id))
else {
return;
};
// Get the type for the parameter corresponding to the argument the closure with the
// lifetime error we had.
let Some(input) = tcx
.fn_sig(method)
.instantiate_identity()
let Some(method_def_id) = typeck_results.type_dependent_def_id(parent_expr.hir_id) else {
return;
};
let Some(input_arg) = tcx
.fn_sig(method_def_id)
.skip_binder()
.inputs()
.skip_binder()
// Methods have a `self` arg, so `pos` is actually `+ 1` to match the method call arg.
.get(pos + 1)
.get(closure_arg_pos + 1)
else {
return;
};
trace!(?input);
let ty::Param(closure_param) = input.kind() else { return };
// If this isn't a param, then we can't substitute a new closure.
let ty::Param(closure_param) = input_arg.kind() else { return };
// Get the arguments for the found method, only specifying that `Self` is the receiver type.
let args = GenericArgs::for_item(tcx, method, |param, _| {
let Some(possible_rcvr_ty) = typeck_results.node_type_opt(rcvr.hir_id) else { return };
let args = GenericArgs::for_item(tcx, method_def_id, |param, _| {
if param.index == 0 {
possible_rcvr_ty.into()
} else if param.index == closure_param.index {
closure_ty.into()
} else {
self.infcx.var_for_def(expr.span, param)
self.infcx.var_for_def(parent_expr.span, param)
}
});
let preds = tcx.predicates_of(method).instantiate(tcx, args);
let preds = tcx.predicates_of(method_def_id).instantiate(tcx, args);
let ocx = ObligationCtxt::new(&self.infcx);
ocx.register_obligations(preds.iter().map(|(pred, span)| {
@ -1176,7 +1161,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
if ocx.select_all_or_error().is_empty() {
diag.span_suggestion_verbose(
value.span.shrink_to_lo(),
tcx.hir().body(*body).value.peel_blocks().span.shrink_to_lo(),
"dereference the return value",
"*".repeat(count),
Applicability::MachineApplicable,

View File

@ -6,7 +6,38 @@ use std::borrow::Cow;
use std::io::{self, Write};
use super::*;
use itertools::Itertools;
use rustc_graphviz as dot;
use rustc_middle::ty::UniverseIndex;
fn render_outlives_constraint(constraint: &OutlivesConstraint<'_>) -> String {
match constraint.locations {
Locations::All(_) => "All(...)".to_string(),
Locations::Single(loc) => format!("{loc:?}"),
}
}
fn render_universe(u: UniverseIndex) -> String {
if u.is_root() {
return "".to_string();
}
format!("/{:?}", u)
}
fn render_region_vid(rvid: RegionVid, regioncx: &RegionInferenceContext<'_>) -> String {
let universe_str = render_universe(regioncx.region_definition(rvid).universe);
let external_name_str = if let Some(external_name) =
regioncx.region_definition(rvid).external_name.and_then(|e| e.get_name())
{
format!(" ({external_name})")
} else {
"".to_string()
};
format!("{:?}{universe_str}{external_name_str}", rvid)
}
impl<'tcx> RegionInferenceContext<'tcx> {
/// Write out the region constraint graph.
@ -46,10 +77,10 @@ impl<'a, 'this, 'tcx> dot::Labeller<'this> for RawConstraints<'a, 'tcx> {
Some(dot::LabelText::LabelStr(Cow::Borrowed("box")))
}
fn node_label(&'this self, n: &RegionVid) -> dot::LabelText<'this> {
dot::LabelText::LabelStr(format!("{n:?}").into())
dot::LabelText::LabelStr(render_region_vid(*n, self.regioncx).into())
}
fn edge_label(&'this self, e: &OutlivesConstraint<'tcx>) -> dot::LabelText<'this> {
dot::LabelText::LabelStr(format!("{:?}", e.locations).into())
dot::LabelText::LabelStr(render_outlives_constraint(e).into())
}
}
@ -96,8 +127,9 @@ impl<'a, 'this, 'tcx> dot::Labeller<'this> for SccConstraints<'a, 'tcx> {
Some(dot::LabelText::LabelStr(Cow::Borrowed("box")))
}
fn node_label(&'this self, n: &ConstraintSccIndex) -> dot::LabelText<'this> {
let nodes = &self.nodes_per_scc[*n];
dot::LabelText::LabelStr(format!("{n:?} = {nodes:?}").into())
let nodes_str =
self.nodes_per_scc[*n].iter().map(|n| render_region_vid(*n, self.regioncx)).join(", ");
dot::LabelText::LabelStr(format!("SCC({n}) = {{{nodes_str}}}", n = n.as_usize()).into())
}
}

View File

@ -1562,7 +1562,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
// Because this free region must be in the ROOT universe, we
// know it cannot contain any bound universes.
assert!(self.scc_universes[longer_fr_scc] == ty::UniverseIndex::ROOT);
assert!(self.scc_universes[longer_fr_scc].is_root());
debug_assert!(self.scc_values.placeholders_contained_in(longer_fr_scc).next().is_none());
// Only check all of the relations for the main representative of each

View File

@ -213,7 +213,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
let scc = self.constraint_sccs.scc(vid);
// Special handling of higher-ranked regions.
if self.scc_universes[scc] != ty::UniverseIndex::ROOT {
if !self.scc_universes[scc].is_root() {
match self.scc_values.placeholders_contained_in(scc).enumerate().last() {
// If the region contains a single placeholder then they're equal.
Some((0, placeholder)) => {

View File

@ -11,7 +11,7 @@ use std::assert_matches::assert_matches;
use itertools::Itertools;
use rustc_hir as hir;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::type_variable::TypeVariableOrigin;
use rustc_infer::infer::{BoundRegionConversionTime, RegionVariableOrigin};
use rustc_middle::mir::*;
use rustc_middle::ty::{self, Ty};
@ -75,10 +75,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
);
let next_ty_var = || {
self.infcx.next_ty_var(TypeVariableOrigin {
span: body.span,
kind: TypeVariableOriginKind::MiscVariable,
})
self.infcx.next_ty_var(TypeVariableOrigin { span: body.span, param_def_id: None })
};
let output_ty = Ty::new_coroutine(
self.tcx(),

View File

@ -16,7 +16,7 @@ use rustc_index::{IndexSlice, IndexVec};
use rustc_infer::infer::canonical::QueryRegionConstraints;
use rustc_infer::infer::outlives::env::RegionBoundPairs;
use rustc_infer::infer::region_constraints::RegionConstraintData;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::type_variable::TypeVariableOrigin;
use rustc_infer::infer::{
BoundRegion, BoundRegionConversionTime, InferCtxt, NllRegionVariableOrigin,
};
@ -2425,7 +2425,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
ty::RawPtr(_, _) | ty::FnPtr(_) => {
let ty_right = right.ty(body, tcx);
let common_ty = self.infcx.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::MiscVariable,
param_def_id: None,
span: body.source_info(location).span,
});
self.sub_types(

View File

@ -1,6 +1,6 @@
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::ErrorGuaranteed;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::type_variable::TypeVariableOrigin;
use rustc_infer::infer::NllRegionVariableOrigin;
use rustc_infer::infer::{ObligationEmittingRelation, StructurallyRelateAliases};
use rustc_infer::traits::{Obligation, PredicateObligations};
@ -129,10 +129,7 @@ impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> {
// the opaque.
let mut enable_subtyping = |ty, opaque_is_expected| {
let ty_vid = infcx.next_ty_var_id_in_universe(
TypeVariableOrigin {
kind: TypeVariableOriginKind::MiscVariable,
span: self.span(),
},
TypeVariableOrigin { param_def_id: None, span: self.span() },
ty::UniverseIndex::ROOT,
);
@ -437,7 +434,7 @@ impl<'bccx, 'tcx> TypeRelation<'tcx> for NllTypeRelating<'_, 'bccx, 'tcx> {
a: ty::Const<'tcx>,
b: ty::Const<'tcx>,
) -> RelateResult<'tcx, ty::Const<'tcx>> {
let a = self.type_checker.infcx.shallow_resolve(a);
let a = self.type_checker.infcx.shallow_resolve_const(a);
assert!(!a.has_non_region_infer(), "unexpected inference var {:?}", a);
assert!(!b.has_non_region_infer(), "unexpected inference var {:?}", b);

View File

@ -8,8 +8,7 @@ use rustc_ast::{self as ast, Expr, GenericArg, GenericParamKind, Generics, SelfK
use rustc_expand::base::ExtCtxt;
use rustc_span::source_map::respan;
use rustc_span::symbol::{kw, Ident, Symbol};
use rustc_span::Span;
use rustc_span::DUMMY_SP;
use rustc_span::{Span, DUMMY_SP};
use thin_vec::ThinVec;
/// A path, e.g., `::std::option::Option::<i32>` (global). Has support

View File

@ -5,7 +5,7 @@ edition = "2021"
[dependencies]
# tidy-alphabetical-start
ar_archive_writer = "0.1.5"
ar_archive_writer = "0.2.0"
bitflags = "2.4.1"
cc = "1.0.90"
itertools = "0.12"

View File

@ -285,14 +285,7 @@ impl<'a> ArArchiveBuilder<'a> {
.tempfile_in(output.parent().unwrap_or_else(|| Path::new("")))
.map_err(|err| io_error_context("couldn't create a temp file", err))?;
write_archive_to_stream(
archive_tmpfile.as_file_mut(),
&entries,
true,
archive_kind,
true,
false,
)?;
write_archive_to_stream(archive_tmpfile.as_file_mut(), &entries, archive_kind, false)?;
let any_entries = !entries.is_empty();
drop(entries);

View File

@ -2059,7 +2059,7 @@ fn add_library_search_dirs(cmd: &mut dyn Linker, sess: &Session, self_contained:
/// Add options making relocation sections in the produced ELF files read-only
/// and suppressing lazy binding.
fn add_relro_args(cmd: &mut dyn Linker, sess: &Session) {
match sess.opts.unstable_opts.relro_level.unwrap_or(sess.target.relro_level) {
match sess.opts.cg.relro_level.unwrap_or(sess.target.relro_level) {
RelroLevel::Full => cmd.full_relro(),
RelroLevel::Partial => cmd.partial_relro(),
RelroLevel::Off => cmd.no_relro(),
@ -3038,9 +3038,10 @@ fn get_apple_sdk_root(sdk_name: &str) -> Result<String, errors::AppleSdkRootErro
|| sdkroot.contains("MacOSX.platform") => {}
"watchsimulator"
if sdkroot.contains("WatchOS.platform") || sdkroot.contains("MacOSX.platform") => {}
"visionos"
if sdkroot.contains("XROS.platform") || sdkroot.contains("MacOSX.platform") => {}
"visionossimulator"
"xros"
if sdkroot.contains("XRSimulator.platform")
|| sdkroot.contains("MacOSX.platform") => {}
"xrsimulator"
if sdkroot.contains("XROS.platform") || sdkroot.contains("MacOSX.platform") => {}
// Ignore `SDKROOT` if it's not a valid path.
_ if !p.is_absolute() || p == Path::new("/") || !p.exists() => {}

View File

@ -907,8 +907,6 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
module: CachedModuleCodegen,
module_config: &ModuleConfig,
) -> WorkItemResult<B> {
assert!(module_config.emit_obj != EmitObj::None);
let incr_comp_session_dir = cgcx.incr_comp_session_dir.as_ref().unwrap();
let load_from_incr_comp_dir = |output_path: PathBuf, saved_path: &str| {
@ -928,12 +926,6 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
}
};
let object = load_from_incr_comp_dir(
cgcx.output_filenames.temp_path(OutputType::Object, Some(&module.name)),
module.source.saved_files.get("o").unwrap_or_else(|| {
cgcx.create_dcx().emit_fatal(errors::NoSavedObjectFile { cgu_name: &module.name })
}),
);
let dwarf_object =
module.source.saved_files.get("dwo").as_ref().and_then(|saved_dwarf_object_file| {
let dwarf_obj_out = cgcx
@ -955,9 +947,14 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
}
};
let should_emit_obj = module_config.emit_obj != EmitObj::None;
let assembly = load_from_incr_cache(module_config.emit_asm, OutputType::Assembly);
let llvm_ir = load_from_incr_cache(module_config.emit_ir, OutputType::LlvmAssembly);
let bytecode = load_from_incr_cache(module_config.emit_bc, OutputType::Bitcode);
let object = load_from_incr_cache(should_emit_obj, OutputType::Object);
if should_emit_obj && object.is_none() {
cgcx.create_dcx().emit_fatal(errors::NoSavedObjectFile { cgu_name: &module.name })
}
WorkItemResult::Finished(CompiledModule {
name: module.name,

View File

@ -1861,12 +1861,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}
enum ReturnDest<'tcx, V> {
// Do nothing; the return value is indirect or ignored.
/// Do nothing; the return value is indirect or ignored.
Nothing,
// Store the return value to the pointer.
/// Store the return value to the pointer.
Store(PlaceRef<'tcx, V>),
// Store an indirect return value to an operand local place.
/// Store an indirect return value to an operand local place.
IndirectOperand(PlaceRef<'tcx, V>, mir::Local),
// Store a direct return value to an operand local place.
/// Store a direct return value to an operand local place.
DirectOperand(mir::Local),
}

View File

@ -347,8 +347,6 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
/// allocation (because a copy had to be done to adjust things), machine memory will
/// cache the result. (This relies on `AllocMap::get_or` being able to add the
/// owned allocation to the map even when the map is shared.)
///
/// This must only fail if `alloc` contains provenance.
fn adjust_allocation<'b>(
ecx: &InterpCx<'mir, 'tcx, Self>,
id: AllocId,
@ -427,6 +425,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
_prov: (AllocId, Self::ProvenanceExtra),
_size: Size,
_align: Align,
_kind: MemoryKind<Self::MemoryKind>,
) -> InterpResult<'tcx> {
Ok(())
}

View File

@ -227,7 +227,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
self.allocate_raw_ptr(alloc, kind)
}
/// This can fail only if `alloc` contains provenance.
pub fn allocate_raw_ptr(
&mut self,
alloc: Allocation,
@ -355,6 +354,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
(alloc_id, prov),
size,
alloc.align,
kind,
)?;
// Don't forget to remember size and align of this now-dead allocation

View File

@ -168,7 +168,7 @@ impl<'ck, 'mir, 'tcx> TypeVisitor<TyCtxt<'tcx>> for LocalReturnTyVisitor<'ck, 'm
match t.kind() {
ty::FnPtr(_) => {}
ty::Ref(_, _, hir::Mutability::Mut) => {
self.checker.check_op(ops::ty::MutRef(self.kind));
self.checker.check_op(ops::mut_ref::MutRef(self.kind));
t.super_visit_with(self)
}
_ => t.super_visit_with(self),
@ -331,6 +331,11 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
if self.tcx.is_thread_local_static(def_id) {
self.tcx.dcx().span_bug(span, "tls access is checked in `Rvalue::ThreadLocalRef`");
}
if let Some(def_id) = def_id.as_local()
&& let Err(guar) = self.tcx.at(span).check_well_formed(hir::OwnerId { def_id })
{
self.error_emitted = Some(guar);
}
self.check_op_spanned(ops::StaticAccess, span)
}

View File

@ -9,9 +9,10 @@ use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::{ImplSource, Obligation, ObligationCause};
use rustc_middle::mir::{self, CallSource};
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::TraitRef;
use rustc_middle::ty::{suggest_constraining_type_param, Adt, Closure, FnDef, FnPtr, Param, Ty};
use rustc_middle::ty::{GenericArgKind, GenericArgsRef};
use rustc_middle::ty::{
self, suggest_constraining_type_param, Closure, FnDef, FnPtr, GenericArgKind, GenericArgsRef,
Param, TraitRef, Ty,
};
use rustc_middle::util::{call_kind, CallDesugaringKind, CallKind};
use rustc_session::parse::feature_err;
use rustc_span::symbol::sym;
@ -123,7 +124,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
);
}
}
Adt(..) => {
ty::Adt(..) => {
let obligation =
Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref);
@ -620,7 +621,7 @@ impl<'tcx> NonConstOp<'tcx> for ThreadLocalAccess {
}
/// Types that cannot appear in the signature or locals of a `const fn`.
pub mod ty {
pub mod mut_ref {
use super::*;
#[derive(Debug)]

View File

@ -24,20 +24,6 @@ struct AstNoAnn;
impl pprust_ast::PpAnn for AstNoAnn {}
struct HirNoAnn<'tcx> {
tcx: TyCtxt<'tcx>,
}
impl<'tcx> pprust_hir::PpAnn for HirNoAnn<'tcx> {
fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) {
pprust_hir::PpAnn::nested(
&(&self.tcx.hir() as &dyn hir::intravisit::Map<'_>),
state,
nested,
)
}
}
struct AstIdentifiedAnn;
impl pprust_ast::PpAnn for AstIdentifiedAnn {
@ -300,10 +286,7 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) {
)
};
match s {
PpHirMode::Normal => {
let annotation = HirNoAnn { tcx };
f(&annotation)
}
PpHirMode::Normal => f(&tcx),
PpHirMode::Identified => {
let annotation = HirIdentifiedAnn { tcx };
f(&annotation)

View File

@ -208,7 +208,7 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec<TokenTree<TokenStre
Comma => op(","),
Semi => op(";"),
Colon => op(":"),
ModSep => op("::"),
PathSep => op("::"),
RArrow => op("->"),
LArrow => op("<-"),
FatArrow => op("=>"),

View File

@ -533,6 +533,8 @@ declare_features! (
(unstable, more_qualified_paths, "1.54.0", Some(86935)),
/// Allows the `#[must_not_suspend]` attribute.
(unstable, must_not_suspend, "1.57.0", Some(83310)),
/// Make `mut` not reset the binding mode on edition >= 2024.
(incomplete, mut_preserve_binding_mode_2024, "CURRENT_RUSTC_VERSION", Some(123076)),
/// Allows `mut ref` and `mut ref mut` identifier patterns.
(incomplete, mut_ref, "CURRENT_RUSTC_VERSION", Some(123076)),
/// Allows using `#[naked]` on functions.
@ -567,10 +569,14 @@ declare_features! (
(unstable, optimize_attribute, "1.34.0", Some(54882)),
/// Allows postfix match `expr.match { ... }`
(unstable, postfix_match, "CURRENT_RUSTC_VERSION", Some(121618)),
/// Allows `use<'a, 'b, A, B>` in `impl use<...> Trait` for precise capture of generic args.
(incomplete, precise_capturing, "CURRENT_RUSTC_VERSION", Some(123432)),
/// Allows macro attributes on expressions, statements and non-inline modules.
(unstable, proc_macro_hygiene, "1.30.0", Some(54727)),
/// Allows `&raw const $place_expr` and `&raw mut $place_expr` expressions.
(unstable, raw_ref_op, "1.41.0", Some(64490)),
/// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024.
(incomplete, ref_pat_eat_one_layer_2024, "CURRENT_RUSTC_VERSION", Some(123076)),
/// Allows `&` and `&mut` patterns to consume match-ergonomics-inserted references.
(incomplete, ref_pat_everywhere, "CURRENT_RUSTC_VERSION", Some(123076)),
/// Allows using the `#[register_tool]` attribute.

View File

@ -207,7 +207,6 @@ impl DefKind {
| DefKind::Enum
| DefKind::Variant
| DefKind::Trait
| DefKind::OpaqueTy
| DefKind::TyAlias
| DefKind::ForeignTy
| DefKind::TraitAlias
@ -234,7 +233,8 @@ impl DefKind {
| DefKind::Use
| DefKind::ForeignMod
| DefKind::GlobalAsm
| DefKind::Impl { .. } => None,
| DefKind::Impl { .. }
| DefKind::OpaqueTy => None,
}
}

View File

@ -2557,6 +2557,27 @@ pub struct OpaqueTy<'hir> {
/// originating from a trait method. This makes it so that the opaque is
/// lowered as an associated type.
pub in_trait: bool,
/// List of arguments captured via `impl use<'a, P, ...> Trait` syntax.
pub precise_capturing_args: Option<&'hir [PreciseCapturingArg<'hir>]>,
}
#[derive(Debug, Clone, Copy, HashStable_Generic)]
pub enum PreciseCapturingArg<'hir> {
Lifetime(&'hir Lifetime),
/// Non-lifetime argument (type or const)
Param(PreciseCapturingNonLifetimeArg),
}
/// We need to have a [`Node`] for the [`HirId`] that we attach the type/const param
/// resolution to. Lifetimes don't have this problem, and for them, it's actually
/// kind of detrimental to use a custom node type versus just using [`Lifetime`],
/// since resolve_bound_vars operates on `Lifetime`s.
// FIXME(precise_capturing): Investigate storing this as a path instead?
#[derive(Debug, Clone, Copy, HashStable_Generic)]
pub struct PreciseCapturingNonLifetimeArg {
pub hir_id: HirId,
pub ident: Ident,
pub res: Res,
}
/// From whence the opaque type came.
@ -3535,6 +3556,7 @@ pub enum Node<'hir> {
WhereBoundPredicate(&'hir WhereBoundPredicate<'hir>),
// FIXME: Merge into `Node::Infer`.
ArrayLenInfer(&'hir InferArg),
PreciseCapturingNonLifetimeArg(&'hir PreciseCapturingNonLifetimeArg),
// Created by query feeding
Synthetic,
// Span by reference to minimize `Node`'s size
@ -3571,6 +3593,7 @@ impl<'hir> Node<'hir> {
Node::TypeBinding(b) => Some(b.ident),
Node::PatField(f) => Some(f.ident),
Node::ExprField(f) => Some(f.ident),
Node::PreciseCapturingNonLifetimeArg(a) => Some(a.ident),
Node::Param(..)
| Node::AnonConst(..)
| Node::ConstBlock(..)

View File

@ -413,6 +413,9 @@ pub trait Visitor<'v>: Sized {
fn visit_param_bound(&mut self, bounds: &'v GenericBound<'v>) -> Self::Result {
walk_param_bound(self, bounds)
}
fn visit_precise_capturing_arg(&mut self, arg: &'v PreciseCapturingArg<'v>) -> Self::Result {
walk_precise_capturing_arg(self, arg)
}
fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef<'v>) -> Self::Result {
walk_poly_trait_ref(self, t)
}
@ -526,10 +529,15 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V::
try_visit!(visitor.visit_ty(ty));
try_visit!(visitor.visit_generics(generics));
}
ItemKind::OpaqueTy(&OpaqueTy { generics, bounds, .. }) => {
ItemKind::OpaqueTy(&OpaqueTy { generics, bounds, precise_capturing_args, .. }) => {
try_visit!(visitor.visit_id(item.hir_id()));
try_visit!(walk_generics(visitor, generics));
walk_list!(visitor, visit_param_bound, bounds);
if let Some(precise_capturing_args) = precise_capturing_args {
for arg in precise_capturing_args {
try_visit!(visitor.visit_precise_capturing_arg(arg));
}
}
}
ItemKind::Enum(ref enum_definition, ref generics) => {
try_visit!(visitor.visit_generics(generics));
@ -1137,6 +1145,16 @@ pub fn walk_param_bound<'v, V: Visitor<'v>>(
}
}
pub fn walk_precise_capturing_arg<'v, V: Visitor<'v>>(
visitor: &mut V,
arg: &'v PreciseCapturingArg<'v>,
) -> V::Result {
match *arg {
PreciseCapturingArg::Lifetime(lt) => visitor.visit_lifetime(lt),
PreciseCapturingArg::Param(param) => visitor.visit_id(param.hir_id),
}
}
pub fn walk_poly_trait_ref<'v, V: Visitor<'v>>(
visitor: &mut V,
trait_ref: &'v PolyTraitRef<'v>,

View File

@ -14,7 +14,7 @@ fn def_path_hash_depends_on_crate_id() {
// the crate by changing the crate disambiguator (e.g. via bumping the
// crate's version number).
create_session_globals_then(Edition::Edition2024, || {
create_session_globals_then(Edition::Edition2024, None, || {
let id0 = StableCrateId::new(Symbol::intern("foo"), false, vec!["1".to_string()], "");
let id1 = StableCrateId::new(Symbol::intern("foo"), false, vec!["2".to_string()], "");

View File

@ -37,6 +37,8 @@ hir_analysis_auto_deref_reached_recursion_limit = reached the recursion limit wh
.label = deref recursion limit reached
.help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)
hir_analysis_bad_precise_capture = expected {$kind} parameter in `use<...>` precise captures list, found {$found}
hir_analysis_cannot_capture_late_bound_const =
cannot capture late-bound const parameter in {$what}
.label = parameter defined here
@ -111,6 +113,9 @@ hir_analysis_drop_impl_on_wrong_item =
hir_analysis_drop_impl_reservation = reservation `Drop` impls are not supported
hir_analysis_duplicate_precise_capture = cannot capture parameter `{$name}` twice
.label = parameter captured again here
hir_analysis_empty_specialization = specialization impl does not specialize any associated items
.note = impl is a specialization of this impl
@ -214,6 +219,13 @@ hir_analysis_late_bound_lifetime_in_apit = `impl Trait` can only mention lifetim
hir_analysis_late_bound_type_in_apit = `impl Trait` can only mention type parameters from an fn or impl
.label = type parameter declared here
hir_analysis_lifetime_must_be_first = lifetime parameter `{$name}` must be listed before non-lifetime parameters
.label = move the lifetime before this parameter
hir_analysis_lifetime_not_captured = `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list
.label = lifetime captured due to being mentioned in the bounds of the `impl Trait`
.param_label = this lifetime parameter is captured
hir_analysis_lifetimes_or_bounds_mismatch_on_trait =
lifetime parameters or bounds on {$item_kind} `{$ident}` do not match the trait declaration
.label = lifetimes do not match {$item_kind} in trait
@ -339,6 +351,10 @@ hir_analysis_param_in_ty_of_assoc_const_binding =
*[normal] the {$param_def_kind} `{$param_name}` is defined here
}
hir_analysis_param_not_captured = `impl Trait` must mention all {$kind} parameters in scope
.label = {$kind} parameter is implicitly captured by this `impl Trait`
.note = currently, all {$kind} parameters are required to be mentioned in the precise captures list
hir_analysis_paren_sugar_attribute = the `#[rustc_paren_sugar]` attribute is a temporary means of controlling which traits can use parenthetical notation
.help = add `#![feature(unboxed_closures)]` to the crate attributes to use it
@ -355,6 +371,9 @@ hir_analysis_pattern_type_wild_pat = "wildcard patterns are not permitted for pa
hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind}
.label = not allowed in type signatures
hir_analysis_precise_capture_self_alias = `Self` can't be captured in `use<...>` precise captures list, since it is an alias
.label = `Self` is not a generic argument, but an alias to the type of the {$what}
hir_analysis_redundant_lifetime_args = unnecessary lifetime parameter `{$victim}`
.note = you can use the `{$candidate}` lifetime directly, in place of `{$victim}`

View File

@ -1,10 +1,10 @@
use crate::check::intrinsicck::InlineAsmCtxt;
use crate::errors::LinkageType;
use super::compare_impl_item::check_type_bounds;
use super::compare_impl_item::{compare_impl_method, compare_impl_ty};
use super::*;
use rustc_attr as attr;
use rustc_data_structures::unord::{UnordMap, UnordSet};
use rustc_errors::{codes::*, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind};
@ -12,6 +12,7 @@ use rustc_hir::Node;
use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
use rustc_infer::traits::{Obligation, TraitEngineExt as _};
use rustc_lint_defs::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS;
use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
use rustc_middle::middle::stability::EvalResult;
use rustc_middle::traits::ObligationCauseCode;
use rustc_middle::ty::fold::BottomUpFolder;
@ -474,6 +475,133 @@ fn sanity_check_found_hidden_type<'tcx>(
}
}
/// Check that the opaque's precise captures list is valid (if present).
/// We check this for regular `impl Trait`s and also RPITITs, even though the latter
/// are technically GATs.
///
/// This function is responsible for:
/// 1. Checking that all type/const params are mention in the captures list.
/// 2. Checking that all lifetimes that are implicitly captured are mentioned.
/// 3. Asserting that all parameters mentioned in the captures list are invariant.
fn check_opaque_precise_captures<'tcx>(tcx: TyCtxt<'tcx>, opaque_def_id: LocalDefId) {
let hir::OpaqueTy { precise_capturing_args, .. } =
*tcx.hir_node_by_def_id(opaque_def_id).expect_item().expect_opaque_ty();
let Some(precise_capturing_args) = precise_capturing_args else {
// No precise capturing args; nothing to validate
return;
};
let mut expected_captures = UnordSet::default();
let mut seen_params = UnordMap::default();
let mut prev_non_lifetime_param = None;
for arg in precise_capturing_args {
let (hir_id, ident) = match *arg {
hir::PreciseCapturingArg::Param(hir::PreciseCapturingNonLifetimeArg {
hir_id,
ident,
..
}) => {
if prev_non_lifetime_param.is_none() {
prev_non_lifetime_param = Some(ident);
}
(hir_id, ident)
}
hir::PreciseCapturingArg::Lifetime(&hir::Lifetime { hir_id, ident, .. }) => {
if let Some(prev_non_lifetime_param) = prev_non_lifetime_param {
tcx.dcx().emit_err(errors::LifetimesMustBeFirst {
lifetime_span: ident.span,
name: ident.name,
other_span: prev_non_lifetime_param.span,
});
}
(hir_id, ident)
}
};
let ident = ident.normalize_to_macros_2_0();
if let Some(span) = seen_params.insert(ident, ident.span) {
tcx.dcx().emit_err(errors::DuplicatePreciseCapture {
name: ident.name,
first_span: span,
second_span: ident.span,
});
}
match tcx.named_bound_var(hir_id) {
Some(ResolvedArg::EarlyBound(def_id)) => {
expected_captures.insert(def_id);
}
_ => {
tcx.dcx().span_delayed_bug(
tcx.hir().span(hir_id),
"parameter should have been resolved",
);
}
}
}
let variances = tcx.variances_of(opaque_def_id);
let mut def_id = Some(opaque_def_id.to_def_id());
while let Some(generics) = def_id {
let generics = tcx.generics_of(generics);
def_id = generics.parent;
for param in &generics.params {
if expected_captures.contains(&param.def_id) {
assert_eq!(
variances[param.index as usize],
ty::Invariant,
"precise captured param should be invariant"
);
continue;
}
match param.kind {
ty::GenericParamDefKind::Lifetime => {
// Check if the lifetime param was captured but isn't named in the precise captures list.
if variances[param.index as usize] == ty::Invariant {
let param_span =
if let ty::ReEarlyParam(ty::EarlyParamRegion { def_id, .. })
| ty::ReLateParam(ty::LateParamRegion {
bound_region: ty::BoundRegionKind::BrNamed(def_id, _),
..
}) = *tcx
.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local())
{
Some(tcx.def_span(def_id))
} else {
None
};
// FIXME(precise_capturing): Structured suggestion for this would be useful
tcx.dcx().emit_err(errors::LifetimeNotCaptured {
use_span: tcx.def_span(param.def_id),
param_span,
opaque_span: tcx.def_span(opaque_def_id),
});
continue;
}
}
ty::GenericParamDefKind::Type { .. } => {
// FIXME(precise_capturing): Structured suggestion for this would be useful
tcx.dcx().emit_err(errors::ParamNotCaptured {
param_span: tcx.def_span(param.def_id),
opaque_span: tcx.def_span(opaque_def_id),
kind: "type",
});
}
ty::GenericParamDefKind::Const { .. } => {
// FIXME(precise_capturing): Structured suggestion for this would be useful
tcx.dcx().emit_err(errors::ParamNotCaptured {
param_span: tcx.def_span(param.def_id),
opaque_span: tcx.def_span(opaque_def_id),
kind: "const",
});
}
}
}
}
}
fn is_enum_of_nonnullable_ptr<'tcx>(
tcx: TyCtxt<'tcx>,
adt_def: AdtDef<'tcx>,
@ -499,7 +627,7 @@ fn check_static_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) {
ty::Adt(adt_def, args) => !is_enum_of_nonnullable_ptr(tcx, *adt_def, *args),
_ => true,
} {
tcx.dcx().emit_err(LinkageType { span: tcx.def_span(def_id) });
tcx.dcx().emit_err(errors::LinkageType { span: tcx.def_span(def_id) });
}
}
}
@ -566,6 +694,8 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
check_union(tcx, def_id);
}
DefKind::OpaqueTy => {
check_opaque_precise_captures(tcx, def_id);
let origin = tcx.opaque_type_origin(def_id);
if let hir::OpaqueTyOrigin::FnReturn(fn_def_id)
| hir::OpaqueTyOrigin::AsyncFn(fn_def_id) = origin

View File

@ -9,7 +9,7 @@ use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit;
use rustc_hir::{GenericParamKind, ImplItemKind};
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::type_variable::TypeVariableOrigin;
use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::{util, FulfillmentError};
use rustc_middle::ty::error::{ExpectedFound, TypeError};
@ -800,10 +800,10 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx> {
bug!("FIXME(RPITIT): error here");
}
// Replace with infer var
let infer_ty = self.ocx.infcx.next_ty_var(TypeVariableOrigin {
span: self.span,
kind: TypeVariableOriginKind::MiscVariable,
});
let infer_ty = self
.ocx
.infcx
.next_ty_var(TypeVariableOrigin { span: self.span, param_def_id: None });
self.types.insert(proj.def_id, (infer_ty, proj.args));
// Recurse into bounds
for (pred, pred_span) in self

View File

@ -12,7 +12,7 @@ pub fn maybe_expr_static_mut(tcx: TyCtxt<'_>, expr: hir::Expr<'_>) {
let hir_id = expr.hir_id;
if let hir::ExprKind::AddrOf(borrow_kind, m, expr) = expr.kind
&& matches!(borrow_kind, hir::BorrowKind::Ref)
&& let Some(var) = is_path_static_mut(*expr)
&& let Some(var) = path_if_static_mut(tcx, expr)
{
handle_static_mut_ref(tcx, span, var, span.edition().at_least_rust_2024(), m, hir_id);
}
@ -24,7 +24,7 @@ pub fn maybe_stmt_static_mut(tcx: TyCtxt<'_>, stmt: hir::Stmt<'_>) {
&& let hir::PatKind::Binding(ba, _, _, _) = loc.pat.kind
&& let hir::ByRef::Yes(rmutbl) = ba.0
&& let Some(init) = loc.init
&& let Some(var) = is_path_static_mut(*init)
&& let Some(var) = path_if_static_mut(tcx, init)
{
handle_static_mut_ref(
tcx,
@ -37,13 +37,13 @@ pub fn maybe_stmt_static_mut(tcx: TyCtxt<'_>, stmt: hir::Stmt<'_>) {
}
}
fn is_path_static_mut(expr: hir::Expr<'_>) -> Option<String> {
fn path_if_static_mut(tcx: TyCtxt<'_>, expr: &hir::Expr<'_>) -> Option<String> {
if let hir::ExprKind::Path(qpath) = expr.kind
&& let hir::QPath::Resolved(_, path) = qpath
&& let hir::def::Res::Def(def_kind, _) = path.res
&& let hir::def::DefKind::Static { mutability: Mutability::Mut, nested: false } = def_kind
{
return Some(qpath_to_string(&qpath));
return Some(qpath_to_string(&tcx, &qpath));
}
None
}

View File

@ -10,8 +10,8 @@ use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::lang_items::LangItem;
use rustc_hir::ItemKind;
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::infer::{self, RegionResolutionError};
use rustc_infer::infer::{DefineOpaqueTypes, TyCtxtInferExt};
use rustc_infer::traits::Obligation;
use rustc_middle::ty::adjustment::CoerceUnsizedInfo;
use rustc_middle::ty::{self, suggest_constraining_type_params, Ty, TyCtxt, TypeVisitableExt};
@ -189,10 +189,7 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<()
// even if they do not carry that attribute.
use rustc_type_ir::TyKind::*;
match (source.kind(), target.kind()) {
(&Ref(r_a, _, mutbl_a), Ref(r_b, _, mutbl_b))
if infcx.at(&cause, param_env).eq(DefineOpaqueTypes::No, r_a, *r_b).is_ok()
&& mutbl_a == *mutbl_b =>
{
(&Ref(r_a, _, mutbl_a), Ref(r_b, _, mutbl_b)) if r_a == *r_b && mutbl_a == *mutbl_b => {
Ok(())
}
(&RawPtr(_, a_mutbl), &RawPtr(_, b_mutbl)) if a_mutbl == b_mutbl => Ok(()),
@ -230,18 +227,14 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<()
}
}
if let Ok(ok) =
infcx.at(&cause, param_env).eq(DefineOpaqueTypes::No, ty_a, ty_b)
{
if ok.obligations.is_empty() {
res = Err(tcx.dcx().emit_err(errors::DispatchFromDynZST {
span,
name: field.name,
ty: ty_a,
}));
if ty_a == ty_b {
res = Err(tcx.dcx().emit_err(errors::DispatchFromDynZST {
span,
name: field.name,
ty: ty_a,
}));
return false;
}
return false;
}
return true;
@ -433,14 +426,12 @@ pub fn coerce_unsized_info<'tcx>(
// something more accepting, but we use
// equality because we want to be able to
// perform this check without computing
// variance where possible. (This is because
// we may have to evaluate constraint
// variance or constraining opaque types' hidden types.
// (This is because we may have to evaluate constraint
// expressions in the course of execution.)
// See e.g., #41936.
if let Ok(ok) = infcx.at(&cause, param_env).eq(DefineOpaqueTypes::No, a, b) {
if ok.obligations.is_empty() {
return None;
}
if a == b {
return None;
}
// Collect up all fields that were significantly changed

View File

@ -37,7 +37,7 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic
// from the trait itself that *shouldn't* be shown as the source of
// an obligation and instead be skipped. Otherwise we'd use
// `tcx.def_span(def_id);`
let span = rustc_span::DUMMY_SP;
let span = DUMMY_SP;
result.predicates =
tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(std::iter::once((

View File

@ -13,7 +13,7 @@ use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{GenericArg, GenericParam, GenericParamKind, HirIdMap, LifetimeName, Node};
use rustc_hir::{GenericArg, GenericParam, GenericParamKind, HirId, HirIdMap, LifetimeName, Node};
use rustc_macros::extension;
use rustc_middle::bug;
use rustc_middle::hir::nested_filter;
@ -107,7 +107,7 @@ enum Scope<'a> {
/// queried later. However, if we enter an elision scope, we have to
/// later append the elided bound vars to the list and need to know what
/// to append to.
hir_id: hir::HirId,
hir_id: HirId,
s: ScopeRef<'a>,
@ -557,6 +557,50 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
}
}
fn visit_precise_capturing_arg(
&mut self,
arg: &'tcx hir::PreciseCapturingArg<'tcx>,
) -> Self::Result {
match *arg {
hir::PreciseCapturingArg::Lifetime(lt) => match lt.res {
LifetimeName::Param(def_id) => {
self.resolve_lifetime_ref(def_id, lt);
}
LifetimeName::Error => {}
LifetimeName::ImplicitObjectLifetimeDefault
| LifetimeName::Infer
| LifetimeName::Static => {
self.tcx.dcx().emit_err(errors::BadPreciseCapture {
span: lt.ident.span,
kind: "lifetime",
found: format!("`{}`", lt.ident.name),
});
}
},
hir::PreciseCapturingArg::Param(param) => match param.res {
Res::Def(DefKind::TyParam | DefKind::ConstParam, def_id)
| Res::SelfTyParam { trait_: def_id } => {
self.resolve_type_ref(def_id.expect_local(), param.hir_id);
}
Res::Err => {}
Res::SelfTyAlias { alias_to, .. } => {
self.tcx.dcx().emit_err(errors::PreciseCaptureSelfAlias {
span: param.ident.span,
self_span: self.tcx.def_span(alias_to),
what: self.tcx.def_descr(alias_to),
});
}
res => {
self.tcx.dcx().emit_err(errors::BadPreciseCapture {
span: param.ident.span,
kind: "type or const",
found: res.descr().to_string(),
});
}
},
}
}
fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
match item.kind {
hir::ForeignItemKind::Fn(_, _, generics) => {
@ -781,7 +825,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
}
}
fn visit_path(&mut self, path: &hir::Path<'tcx>, hir_id: hir::HirId) {
fn visit_path(&mut self, path: &hir::Path<'tcx>, hir_id: HirId) {
for (i, segment) in path.segments.iter().enumerate() {
let depth = path.segments.len() - i - 1;
if let Some(args) = segment.args {
@ -983,7 +1027,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
}
}
fn record_late_bound_vars(&mut self, hir_id: hir::HirId, binder: Vec<ty::BoundVariableKind>) {
fn record_late_bound_vars(&mut self, hir_id: HirId, binder: Vec<ty::BoundVariableKind>) {
if let Some(old) = self.map.late_bound_vars.insert(hir_id, binder) {
bug!(
"overwrote bound vars for {hir_id:?}:\nold={old:?}\nnew={:?}",
@ -1010,12 +1054,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
/// already in scope (for a fn item, that will be 0, but for a method it might not be). Late
/// bound lifetimes are resolved by name and associated with a binder ID (`binder_id`), so the
/// ordering is not important there.
fn visit_early_late<F>(
&mut self,
hir_id: hir::HirId,
generics: &'tcx hir::Generics<'tcx>,
walk: F,
) where
fn visit_early_late<F>(&mut self, hir_id: HirId, generics: &'tcx hir::Generics<'tcx>, walk: F)
where
F: for<'b, 'c> FnOnce(&'b mut BoundVarContext<'c, 'tcx>),
{
let mut named_late_bound_vars = 0;
@ -1062,7 +1102,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
self.with(scope, walk);
}
fn visit_early<F>(&mut self, hir_id: hir::HirId, generics: &'tcx hir::Generics<'tcx>, walk: F)
fn visit_early<F>(&mut self, hir_id: HirId, generics: &'tcx hir::Generics<'tcx>, walk: F)
where
F: for<'b, 'c> FnOnce(&'b mut BoundVarContext<'c, 'tcx>),
{
@ -1288,7 +1328,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
);
}
fn resolve_type_ref(&mut self, param_def_id: LocalDefId, hir_id: hir::HirId) {
fn resolve_type_ref(&mut self, param_def_id: LocalDefId, hir_id: HirId) {
// Walk up the scope chain, tracking the number of fn scopes
// that we pass through, until we find a lifetime with the
// given name or we run out of scopes.

View File

@ -10,6 +10,9 @@ use rustc_span::{symbol::Ident, Span, Symbol};
mod pattern_types;
pub use pattern_types::*;
mod precise_captures;
pub(crate) use precise_captures::*;
#[derive(Diagnostic)]
#[diag(hir_analysis_ambiguous_assoc_item)]
pub struct AmbiguousAssocItem<'a> {

View File

@ -0,0 +1,63 @@
use rustc_macros::Diagnostic;
use rustc_span::{Span, Symbol};
#[derive(Diagnostic)]
#[diag(hir_analysis_param_not_captured)]
#[note]
pub struct ParamNotCaptured {
#[primary_span]
pub param_span: Span,
#[label]
pub opaque_span: Span,
pub kind: &'static str,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_lifetime_not_captured)]
pub struct LifetimeNotCaptured {
#[primary_span]
pub use_span: Span,
#[label(hir_analysis_param_label)]
pub param_span: Option<Span>,
#[label]
pub opaque_span: Span,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_bad_precise_capture)]
pub struct BadPreciseCapture {
#[primary_span]
pub span: Span,
pub kind: &'static str,
pub found: String,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_precise_capture_self_alias)]
pub struct PreciseCaptureSelfAlias {
#[primary_span]
pub span: Span,
#[label]
pub self_span: Span,
pub what: &'static str,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_duplicate_precise_capture)]
pub struct DuplicatePreciseCapture {
#[primary_span]
pub first_span: Span,
pub name: Symbol,
#[label]
pub second_span: Span,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_lifetime_must_be_first)]
pub struct LifetimesMustBeFirst {
#[primary_span]
pub lifetime_span: Span,
pub name: Symbol,
#[label]
pub other_span: Span,
}

View File

@ -35,7 +35,7 @@ use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{walk_generics, Visitor as _};
use rustc_hir::{GenericArg, GenericArgs};
use rustc_hir::{GenericArg, GenericArgs, HirId};
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::ObligationCause;
use rustc_middle::middle::stability::AllowUnstable;
@ -158,7 +158,7 @@ pub trait HirTyLowerer<'tcx> {
fn probe_adt(&self, span: Span, ty: Ty<'tcx>) -> Option<ty::AdtDef<'tcx>>;
/// Record the lowered type of a HIR node in this context.
fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, span: Span);
fn record_ty(&self, hir_id: HirId, ty: Ty<'tcx>, span: Span);
/// The inference context of the lowering context if applicable.
fn infcx(&self) -> Option<&InferCtxt<'tcx>>;
@ -999,7 +999,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
#[instrument(level = "debug", skip_all, ret)]
pub fn lower_assoc_path(
&self,
hir_ref_id: hir::HirId,
hir_ref_id: HirId,
span: Span,
qself_ty: Ty<'tcx>,
qself: &'tcx hir::Ty<'tcx>,
@ -1200,7 +1200,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
segment: &hir::PathSegment<'tcx>,
adt_did: DefId,
self_ty: Ty<'tcx>,
block: hir::HirId,
block: HirId,
span: Span,
) -> Result<Option<(Ty<'tcx>, DefId)>, ErrorGuaranteed> {
let tcx = self.tcx();
@ -1349,13 +1349,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}
}
fn probe_assoc_ty(
&self,
name: Ident,
block: hir::HirId,
span: Span,
scope: DefId,
) -> Option<DefId> {
fn probe_assoc_ty(&self, name: Ident, block: HirId, span: Span, scope: DefId) -> Option<DefId> {
let (item, def_scope) = self.probe_assoc_ty_unchecked(name, block, scope)?;
self.check_assoc_ty(item, name, def_scope, block, span);
Some(item)
@ -1364,7 +1358,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
fn probe_assoc_ty_unchecked(
&self,
name: Ident,
block: hir::HirId,
block: HirId,
scope: DefId,
) -> Option<(DefId, DefId)> {
let tcx = self.tcx();
@ -1381,14 +1375,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
Some((item.def_id, def_scope))
}
fn check_assoc_ty(
&self,
item: DefId,
name: Ident,
def_scope: DefId,
block: hir::HirId,
span: Span,
) {
fn check_assoc_ty(&self, item: DefId, name: Ident, def_scope: DefId, block: HirId, span: Span) {
let tcx = self.tcx();
let kind = DefKind::AssocTy;
@ -1714,7 +1701,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
&self,
opt_self_ty: Option<Ty<'tcx>>,
path: &hir::Path<'tcx>,
hir_id: hir::HirId,
hir_id: HirId,
permit_variants: bool,
) -> Ty<'tcx> {
debug!(?path.res, ?opt_self_ty, ?path.segments);
@ -1898,7 +1885,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
///
/// Early-bound type parameters get lowered to [`ty::Param`]
/// and late-bound ones to [`ty::Bound`].
pub(crate) fn lower_ty_param(&self, hir_id: hir::HirId) -> Ty<'tcx> {
pub(crate) fn lower_ty_param(&self, hir_id: HirId) -> Ty<'tcx> {
let tcx = self.tcx();
match tcx.named_bound_var(hir_id) {
Some(rbv::ResolvedArg::LateBound(debruijn, index, def_id)) => {
@ -1925,7 +1912,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
///
/// Early-bound const parameters get lowered to [`ty::ConstKind::Param`]
/// and late-bound ones to [`ty::ConstKind::Bound`].
pub(crate) fn lower_const_param(&self, hir_id: hir::HirId, param_ty: Ty<'tcx>) -> Const<'tcx> {
pub(crate) fn lower_const_param(&self, hir_id: HirId, param_ty: Ty<'tcx>) -> Const<'tcx> {
let tcx = self.tcx();
match tcx.named_bound_var(hir_id) {
Some(rbv::ResolvedArg::EarlyBound(def_id)) => {
@ -2352,7 +2339,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
#[instrument(level = "debug", skip(self, hir_id, unsafety, abi, decl, generics, hir_ty), ret)]
pub fn lower_fn_ty(
&self,
hir_id: hir::HirId,
hir_id: HirId,
unsafety: hir::Unsafety,
abi: abi::Abi,
decl: &hir::FnDecl<'tcx>,
@ -2480,7 +2467,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
/// corresponds to the return type.
fn suggest_trait_fn_ty_for_impl_fn_infer(
&self,
fn_hir_id: hir::HirId,
fn_hir_id: HirId,
arg_idx: Option<usize>,
) -> Option<Ty<'tcx>> {
let tcx = self.tcx();

View File

@ -9,9 +9,10 @@ use rustc_ast_pretty::pp::Breaks::{Consistent, Inconsistent};
use rustc_ast_pretty::pp::{self, Breaks};
use rustc_ast_pretty::pprust::{Comments, PrintState};
use rustc_hir as hir;
use rustc_hir::LifetimeParamKind;
use rustc_hir::{BindingAnnotation, ByRef, GenericArg, GenericParam, GenericParamKind, Node, Term};
use rustc_hir::{GenericBound, PatKind, RangeEnd, TraitBoundModifier};
use rustc_hir::{
BindingAnnotation, ByRef, GenericArg, GenericBound, GenericParam, GenericParamKind, HirId,
LifetimeParamKind, Node, PatKind, RangeEnd, Term, TraitBoundModifier,
};
use rustc_span::source_map::SourceMap;
use rustc_span::symbol::{kw, Ident, Symbol};
use rustc_span::FileName;
@ -20,7 +21,7 @@ use rustc_target::spec::abi::Abi;
use std::cell::Cell;
use std::vec;
pub fn id_to_string(map: &dyn rustc_hir::intravisit::Map<'_>, hir_id: hir::HirId) -> String {
pub fn id_to_string(map: &dyn rustc_hir::intravisit::Map<'_>, hir_id: HirId) -> String {
to_string(&map, |s| s.print_node(map.hir_node(hir_id)))
}
@ -28,7 +29,7 @@ pub enum AnnNode<'a> {
Name(&'a Symbol),
Block(&'a hir::Block<'a>),
Item(&'a hir::Item<'a>),
SubItem(hir::HirId),
SubItem(HirId),
Expr(&'a hir::Expr<'a>),
Pat(&'a hir::Pat<'a>),
Arm(&'a hir::Arm<'a>),
@ -49,10 +50,6 @@ pub trait PpAnn {
fn post(&self, _state: &mut State<'_>, _node: AnnNode<'_>) {}
}
pub struct NoAnn;
impl PpAnn for NoAnn {}
impl PpAnn for &dyn rustc_hir::intravisit::Map<'_> {
fn nested(&self, state: &mut State<'_>, nested: Nested) {
match nested {
@ -69,12 +66,12 @@ impl PpAnn for &dyn rustc_hir::intravisit::Map<'_> {
pub struct State<'a> {
pub s: pp::Printer,
comments: Option<Comments<'a>>,
attrs: &'a dyn Fn(hir::HirId) -> &'a [ast::Attribute],
attrs: &'a dyn Fn(HirId) -> &'a [ast::Attribute],
ann: &'a (dyn PpAnn + 'a),
}
impl<'a> State<'a> {
fn attrs(&self, id: hir::HirId) -> &'a [ast::Attribute] {
fn attrs(&self, id: HirId) -> &'a [ast::Attribute] {
(self.attrs)(id)
}
@ -99,6 +96,7 @@ impl<'a> State<'a> {
Node::PatField(a) => self.print_patfield(a),
Node::Arm(a) => self.print_arm(a),
Node::Infer(_) => self.word("_"),
Node::PreciseCapturingNonLifetimeArg(param) => self.print_ident(param.ident),
Node::Block(a) => {
// Containing cbox, will be closed by print-block at `}`.
self.cbox(INDENT_UNIT);
@ -163,7 +161,7 @@ pub fn print_crate<'a>(
krate: &hir::Mod<'_>,
filename: FileName,
input: String,
attrs: &'a dyn Fn(hir::HirId) -> &'a [ast::Attribute],
attrs: &'a dyn Fn(HirId) -> &'a [ast::Attribute],
ann: &'a dyn PpAnn,
) -> String {
let mut s = State {
@ -190,16 +188,16 @@ where
printer.s.eof()
}
pub fn ty_to_string(ty: &hir::Ty<'_>) -> String {
to_string(&NoAnn, |s| s.print_type(ty))
pub fn ty_to_string(ann: &dyn PpAnn, ty: &hir::Ty<'_>) -> String {
to_string(ann, |s| s.print_type(ty))
}
pub fn qpath_to_string(segment: &hir::QPath<'_>) -> String {
to_string(&NoAnn, |s| s.print_qpath(segment, false))
pub fn qpath_to_string(ann: &dyn PpAnn, segment: &hir::QPath<'_>) -> String {
to_string(ann, |s| s.print_qpath(segment, false))
}
pub fn pat_to_string(pat: &hir::Pat<'_>) -> String {
to_string(&NoAnn, |s| s.print_pat(pat))
pub fn pat_to_string(ann: &dyn PpAnn, pat: &hir::Pat<'_>) -> String {
to_string(ann, |s| s.print_pat(pat))
}
impl<'a> State<'a> {

View File

@ -46,6 +46,10 @@ hir_typeck_ctor_is_private = tuple struct constructor `{$def}` is private
hir_typeck_deref_is_empty = this expression `Deref`s to `{$deref_ty}` which implements `is_empty`
hir_typeck_dereferencing_mut_binding = dereferencing `mut` binding
.label = `mut` dereferences the type of this binding
.help = this will change in edition 2024
hir_typeck_expected_default_return_type = expected `()` because of default return type
hir_typeck_expected_return_type = expected `{$expected}` because of return type

View File

@ -5,7 +5,7 @@ use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::def_id::LocalDefId;
use rustc_hir::{self as hir, ExprKind, PatKind};
use rustc_hir_pretty::ty_to_string;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::type_variable::TypeVariableOrigin;
use rustc_middle::ty::{self, Ty};
use rustc_span::Span;
use rustc_trait_selection::traits::{
@ -67,10 +67,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// arm for inconsistent arms or to the whole match when a `()` type
// is required).
Expectation::ExpectHasType(ety) if ety != Ty::new_unit(self.tcx) => ety,
_ => self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::MiscVariable,
span: expr.span,
}),
_ => self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr.span }),
};
CoerceMany::with_coercion_sites(coerce_first, arms)
};
@ -395,7 +392,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return self.get_fn_decl(hir_id).map(|(_, fn_decl, _)| {
let (ty, span) = match fn_decl.output {
hir::FnRetTy::DefaultReturn(span) => ("()".to_string(), span),
hir::FnRetTy::Return(ty) => (ty_to_string(ty), ty.span),
hir::FnRetTy::Return(ty) => (ty_to_string(&self.tcx, ty), ty.span),
};
(span, format!("expected `{ty}` because of this return type"))
});
@ -578,10 +575,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// ...but otherwise we want to use any supertype of the
// scrutinee. This is sort of a workaround, see note (*) in
// `check_pat` for some details.
let scrut_ty = self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::TypeInference,
span: scrut.span,
});
let scrut_ty =
self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: scrut.span });
self.check_expr_has_type_or_error(scrut, scrut_ty, |_| {});
scrut_ty
}

View File

@ -13,10 +13,7 @@ use rustc_infer::{
infer,
traits::{self, Obligation},
};
use rustc_infer::{
infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind},
traits::ObligationCause,
};
use rustc_infer::{infer::type_variable::TypeVariableOrigin, traits::ObligationCause};
use rustc_middle::ty::adjustment::{
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability,
};
@ -180,18 +177,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
infer::FnCall,
closure_args.coroutine_closure_sig(),
);
let tupled_upvars_ty = self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::TypeInference,
span: callee_expr.span,
});
let tupled_upvars_ty = self
.next_ty_var(TypeVariableOrigin { param_def_id: None, span: callee_expr.span });
// We may actually receive a coroutine back whose kind is different
// from the closure that this dispatched from. This is because when
// we have no captures, we automatically implement `FnOnce`. This
// impl forces the closure kind to `FnOnce` i.e. `u8`.
let kind_ty = self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::TypeInference,
span: callee_expr.span,
});
let kind_ty = self
.next_ty_var(TypeVariableOrigin { param_def_id: None, span: callee_expr.span });
let call_sig = self.tcx.mk_fn_sig(
[coroutine_closure_sig.tupled_inputs_ty],
coroutine_closure_sig.to_coroutine(
@ -305,10 +298,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Ty::new_tup_from_iter(
self.tcx,
arg_exprs.iter().map(|e| {
self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::TypeInference,
span: e.span,
})
self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: e.span })
}),
)
});
@ -724,7 +714,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
def::CtorOf::Variant => "enum variant",
};
let removal_span = callee_expr.span.shrink_to_hi().to(call_expr.span.shrink_to_hi());
unit_variant = Some((removal_span, descr, rustc_hir_pretty::qpath_to_string(qpath)));
unit_variant =
Some((removal_span, descr, rustc_hir_pretty::qpath_to_string(&self.tcx, qpath)));
}
let callee_ty = self.resolve_vars_if_possible(callee_ty);

View File

@ -8,7 +8,7 @@ use rustc_hir::def::DefKind;
use rustc_hir::intravisit::Visitor;
use rustc_hir::lang_items::LangItem;
use rustc_hir_analysis::check::{check_function_signature, forbid_intrinsic_abi};
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::type_variable::TypeVariableOrigin;
use rustc_infer::infer::RegionVariableOrigin;
use rustc_middle::ty::{self, Binder, Ty, TyCtxt};
use rustc_span::def_id::LocalDefId;
@ -123,8 +123,7 @@ pub(super) fn check_fn<'a, 'tcx>(
// We have special-cased the case where the function is declared
// `-> dyn Foo` and we don't actually relate it to the
// `fcx.ret_coercion`, so just instantiate a type variable.
actual_return_ty =
fcx.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::DynReturnFn, span });
actual_return_ty = fcx.next_ty_var(TypeVariableOrigin { param_def_id: None, span });
debug!("actual_return_ty replaced with {:?}", actual_return_ty);
}

View File

@ -6,7 +6,7 @@ use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::lang_items::LangItem;
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::type_variable::TypeVariableOrigin;
use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes};
use rustc_infer::infer::{InferOk, InferResult};
use rustc_macros::{TypeFoldable, TypeVisitable};
@ -72,10 +72,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let parent_args =
GenericArgs::identity_for_item(tcx, tcx.typeck_root_def_id(expr_def_id.to_def_id()));
let tupled_upvars_ty = self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::ClosureSynthetic,
span: expr_span,
});
let tupled_upvars_ty =
self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr_span });
// FIXME: We could probably actually just unify this further --
// instead of having a `FnSig` and a `Option<CoroutineTypes>`,
@ -102,11 +100,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Create a type variable (for now) to represent the closure kind.
// It will be unified during the upvar inference phase (`upvar.rs`)
None => self.next_ty_var(TypeVariableOrigin {
// FIXME(eddyb) distinguish closure kind inference variables from the rest.
kind: TypeVariableOriginKind::ClosureSynthetic,
span: expr_span,
}),
None => {
self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr_span })
}
};
let closure_args = ty::ClosureArgs::new(
@ -126,7 +122,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)
| hir::CoroutineKind::Coroutine(_) => {
let yield_ty = self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::ClosureSynthetic,
param_def_id: None,
span: expr_span,
});
self.require_type_is_sized(yield_ty, expr_span, traits::SizedYieldType);
@ -138,7 +134,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// not a problem.
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _) => {
let yield_ty = self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::ClosureSynthetic,
param_def_id: None,
span: expr_span,
});
self.require_type_is_sized(yield_ty, expr_span, traits::SizedYieldType);
@ -166,10 +162,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Resume type defaults to `()` if the coroutine has no argument.
let resume_ty = liberated_sig.inputs().get(0).copied().unwrap_or(tcx.types.unit);
let interior = self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::ClosureSynthetic,
span: expr_span,
});
let interior =
self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr_span });
self.deferred_coroutine_interiors.borrow_mut().push((
expr_def_id,
body.id(),
@ -181,11 +175,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// later during upvar analysis. Regular coroutines always have the kind
// ty of `().`
let kind_ty = match kind {
hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure) => self
.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::ClosureSynthetic,
span: expr_span,
}),
hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure) => {
self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr_span })
}
_ => tcx.types.unit,
};
@ -219,30 +211,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
};
// Compute all of the variables that will be used to populate the coroutine.
let resume_ty = self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::ClosureSynthetic,
span: expr_span,
});
let interior = self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::ClosureSynthetic,
span: expr_span,
});
let resume_ty =
self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr_span });
let interior =
self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr_span });
let closure_kind_ty = match expected_kind {
Some(kind) => Ty::from_closure_kind(tcx, kind),
// Create a type variable (for now) to represent the closure kind.
// It will be unified during the upvar inference phase (`upvar.rs`)
None => self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::ClosureSynthetic,
span: expr_span,
}),
None => {
self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr_span })
}
};
let coroutine_captures_by_ref_ty = self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::ClosureSynthetic,
span: expr_span,
});
let coroutine_captures_by_ref_ty =
self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr_span });
let closure_args = ty::CoroutineClosureArgs::new(
tcx,
ty::CoroutineClosureArgsParts {
@ -274,16 +259,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Create a type variable (for now) to represent the closure kind.
// It will be unified during the upvar inference phase (`upvar.rs`)
None => self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::ClosureSynthetic,
span: expr_span,
}),
None => {
self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr_span })
}
};
let coroutine_upvars_ty = self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::ClosureSynthetic,
span: expr_span,
});
let coroutine_upvars_ty =
self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr_span });
// We need to turn the liberated signature that we got from HIR, which
// looks something like `|Args...| -> T`, into a signature that is suitable

View File

@ -43,7 +43,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::Expr;
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::type_variable::TypeVariableOrigin;
use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult};
use rustc_infer::traits::TraitEngineExt as _;
use rustc_infer::traits::{IfExpressionCause, MatchExpressionArmCause, TraitEngine};
@ -59,8 +59,7 @@ use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt};
use rustc_session::parse::feature_err;
use rustc_span::symbol::sym;
use rustc_span::DesugaringKind;
use rustc_span::{BytePos, Span};
use rustc_span::{BytePos, DesugaringKind, Span, DUMMY_SP};
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::infer::InferCtxtExt as _;
use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt;
@ -280,10 +279,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
if b.is_ty_var() {
// Two unresolved type variables: create a `Coerce` predicate.
let target_ty = if self.use_lub {
self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::LatticeVariable,
span: self.cause.span,
})
self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: self.cause.span })
} else {
b
};
@ -582,10 +578,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
// the `CoerceUnsized` target type and the expected type.
// We only have the latter, so we use an inference variable
// for the former and let type inference do the rest.
let origin = TypeVariableOrigin {
kind: TypeVariableOriginKind::MiscVariable,
span: self.cause.span,
};
let origin = TypeVariableOrigin { param_def_id: None, span: self.cause.span };
let coerce_target = self.next_ty_var(origin);
let mut coercion = self.unify_and(coerce_target, target, |target| {
let unsize = Adjustment { kind: Adjust::Pointer(PointerCoercion::Unsize), target };
@ -1051,7 +1044,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let source = self.resolve_vars_with_obligations(expr_ty);
debug!("coercion::can_with_predicates({:?} -> {:?})", source, target);
let cause = self.cause(rustc_span::DUMMY_SP, ObligationCauseCode::ExprAssignable);
let cause = self.cause(DUMMY_SP, ObligationCauseCode::ExprAssignable);
// We don't ever need two-phase here since we throw out the result of the coercion
let coerce = Coerce::new(self, cause, AllowTwoPhase::No);
self.probe(|_| {
@ -1068,11 +1061,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// how many dereference steps needed to achieve `expr_ty <: target`. If
/// it's not possible, return `None`.
pub fn deref_steps(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> Option<usize> {
let cause = self.cause(rustc_span::DUMMY_SP, ObligationCauseCode::ExprAssignable);
let cause = self.cause(DUMMY_SP, ObligationCauseCode::ExprAssignable);
// We don't ever need two-phase here since we throw out the result of the coercion
let coerce = Coerce::new(self, cause, AllowTwoPhase::No);
coerce
.autoderef(rustc_span::DUMMY_SP, expr_ty)
.autoderef(DUMMY_SP, expr_ty)
.find_map(|(ty, steps)| self.probe(|_| coerce.unify(ty, target)).ok().map(|_| steps))
}
@ -1083,7 +1076,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// trait or region sub-obligations. (presumably we could, but it's not
/// particularly important for diagnostics...)
pub fn deref_once_mutably_for_diagnostic(&self, expr_ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
self.autoderef(rustc_span::DUMMY_SP, expr_ty).nth(1).and_then(|(deref_ty, _)| {
self.autoderef(DUMMY_SP, expr_ty).nth(1).and_then(|(deref_ty, _)| {
self.infcx
.type_implements_trait(
self.tcx.lang_items().deref_mut_trait()?,

View File

@ -337,10 +337,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty_op: |ty| {
if let ty::Infer(infer) = ty.kind() {
match infer {
ty::TyVar(_) => self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::MiscVariable,
span: DUMMY_SP,
}),
ty::TyVar(_) => self
.next_ty_var(TypeVariableOrigin { param_def_id: None, span: DUMMY_SP }),
ty::IntVar(_) => self.next_int_var(),
ty::FloatVar(_) => self.next_float_var(),
ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => {
@ -356,10 +354,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let ty::ConstKind::Infer(_) = ct.kind() {
self.next_const_var(
ct.ty(),
ConstVariableOrigin {
kind: ConstVariableOriginKind::MiscVariable,
span: DUMMY_SP,
},
ConstVariableOrigin { param_def_id: None, span: DUMMY_SP },
)
} else {
ct

View File

@ -632,3 +632,11 @@ pub enum SuggestBoxingForReturnImplTrait {
ends: Vec<Span>,
},
}
#[derive(LintDiagnostic)]
#[diag(hir_typeck_dereferencing_mut_binding)]
pub struct DereferencingMutBinding {
#[label]
#[help]
pub span: Span,
}

View File

@ -1,4 +1,4 @@
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::type_variable::TypeVariableOrigin;
use rustc_middle::ty::{self, Ty};
use rustc_span::Span;
@ -110,8 +110,7 @@ impl<'a, 'tcx> Expectation<'tcx> {
/// Like `only_has_type`, but instead of returning `None` if no
/// hard constraint exists, creates a fresh type variable.
pub(super) fn coercion_target_type(self, fcx: &FnCtxt<'a, 'tcx>, span: Span) -> Ty<'tcx> {
self.only_has_type(fcx).unwrap_or_else(|| {
fcx.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::MiscVariable, span })
})
self.only_has_type(fcx)
.unwrap_or_else(|| fcx.next_ty_var(TypeVariableOrigin { param_def_id: None, span }))
}
}

View File

@ -37,7 +37,7 @@ use rustc_hir::lang_items::LangItem;
use rustc_hir::{ExprKind, HirId, QPath};
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer as _;
use rustc_infer::infer;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::type_variable::TypeVariableOrigin;
use rustc_infer::infer::DefineOpaqueTypes;
use rustc_infer::infer::InferOk;
use rustc_infer::traits::query::NoSolution;
@ -54,7 +54,6 @@ use rustc_span::source_map::Spanned;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::Span;
use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
use rustc_target::spec::abi::Abi::RustIntrinsic;
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt as _;
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
@ -81,10 +80,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return Ty::new_error(self.tcx(), reported);
}
let adj_ty = self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::AdjustmentType,
span: expr.span,
});
let adj_ty =
self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr.span });
self.apply_adjustments(
expr,
vec![Adjustment { kind: Adjust::NeverToAny, target: adj_ty }],
@ -541,16 +538,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let ty::FnDef(did, _) = *ty.kind() {
let fn_sig = ty.fn_sig(tcx);
if tcx.fn_sig(did).skip_binder().abi() == RustIntrinsic
&& tcx.item_name(did) == sym::transmute
{
if tcx.is_intrinsic(did, sym::transmute) {
let Some(from) = fn_sig.inputs().skip_binder().get(0) else {
let e = self.dcx().span_delayed_bug(
span_bug!(
tcx.def_span(did),
"intrinsic fn `transmute` defined with no parameters",
"intrinsic fn `transmute` defined with no parameters"
);
self.set_tainted_by_errors(e);
return Ty::new_error(tcx, e);
};
let to = fn_sig.output().skip_binder();
// We defer the transmute to the end of typeck, once all inference vars have
@ -1420,10 +1413,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
_ => None,
})
.unwrap_or_else(|| {
self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::TypeInference,
span: expr.span,
})
self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr.span })
});
let mut coerce = CoerceMany::with_coercion_sites(coerce_to, args);
assert_eq!(self.diverges.get(), Diverges::Maybe);
@ -1434,10 +1424,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
coerce.complete(self)
} else {
self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::TypeInference,
span: expr.span,
})
self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr.span })
};
let array_len = args.len() as u64;
self.suggest_array_len(expr, array_len);
@ -1520,10 +1507,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
(uty, uty)
}
None => {
let ty = self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::MiscVariable,
span: element.span,
});
let ty =
self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: element.span });
let element_ty = self.check_expr_has_type_or_error(element, ty, |_| {});
(element_ty, ty)
}
@ -2866,7 +2851,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
span: Span,
base_ty: Ty<'tcx>,
mod_id: DefId,
hir_id: hir::HirId,
hir_id: HirId,
) -> Vec<(Vec<&'tcx ty::FieldDef>, GenericArgsRef<'tcx>)> {
debug!("get_field_candidates(span: {:?}, base_t: {:?}", span, base_ty);

View File

@ -13,7 +13,7 @@ use rustc_data_structures::fx::FxIndexMap;
use rustc_hir as hir;
use rustc_hir::def::Res;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::PatKind;
use rustc_hir::{HirId, PatKind};
use rustc_infer::infer::InferCtxt;
use rustc_middle::hir::place::ProjectionKind;
use rustc_middle::mir::FakeReadCause;
@ -39,20 +39,20 @@ pub trait Delegate<'tcx> {
/// diagnostics. Around pattern matching such as `let pat = expr`, the diagnostic
/// id will be the id of the expression `expr` but the place itself will have
/// the id of the binding in the pattern `pat`.
fn consume(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId);
fn consume(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: HirId);
/// The value found at `place` is being borrowed with kind `bk`.
/// `diag_expr_id` is the id used for diagnostics (see `consume` for more details).
fn borrow(
&mut self,
place_with_id: &PlaceWithHirId<'tcx>,
diag_expr_id: hir::HirId,
diag_expr_id: HirId,
bk: ty::BorrowKind,
);
/// The value found at `place` is being copied.
/// `diag_expr_id` is the id used for diagnostics (see `consume` for more details).
fn copy(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId) {
fn copy(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) {
// In most cases, copying data from `x` is equivalent to doing `*&x`, so by default
// we treat a copy of `x` as a borrow of `x`.
self.borrow(place_with_id, diag_expr_id, ty::BorrowKind::ImmBorrow)
@ -60,12 +60,12 @@ pub trait Delegate<'tcx> {
/// The path at `assignee_place` is being assigned to.
/// `diag_expr_id` is the id used for diagnostics (see `consume` for more details).
fn mutate(&mut self, assignee_place: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId);
fn mutate(&mut self, assignee_place: &PlaceWithHirId<'tcx>, diag_expr_id: HirId);
/// The path at `binding_place` is a binding that is being initialized.
///
/// This covers cases such as `let x = 42;`
fn bind(&mut self, binding_place: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId) {
fn bind(&mut self, binding_place: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) {
// Bindings can normally be treated as a regular assignment, so by default we
// forward this to the mutate callback.
self.mutate(binding_place, diag_expr_id)
@ -76,7 +76,7 @@ pub trait Delegate<'tcx> {
&mut self,
place_with_id: &PlaceWithHirId<'tcx>,
cause: FakeReadCause,
diag_expr_id: hir::HirId,
diag_expr_id: HirId,
);
}
@ -154,7 +154,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
self.mc.tcx()
}
fn delegate_consume(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId) {
fn delegate_consume(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) {
delegate_consume(&self.mc, self.delegate, place_with_id, diag_expr_id)
}
@ -775,8 +775,8 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
/// closure as the DefId.
fn walk_captures(&mut self, closure_expr: &hir::Closure<'_>) {
fn upvar_is_local_variable(
upvars: Option<&FxIndexMap<hir::HirId, hir::Upvar>>,
upvar_id: hir::HirId,
upvars: Option<&FxIndexMap<HirId, hir::Upvar>>,
upvar_id: HirId,
body_owner_is_closure: bool,
) -> bool {
upvars.map(|upvars| !upvars.contains_key(&upvar_id)).unwrap_or(body_owner_is_closure)
@ -902,7 +902,7 @@ fn delegate_consume<'a, 'tcx>(
mc: &mc::MemCategorizationContext<'a, 'tcx>,
delegate: &mut (dyn Delegate<'tcx> + 'a),
place_with_id: &PlaceWithHirId<'tcx>,
diag_expr_id: hir::HirId,
diag_expr_id: HirId,
) {
debug!("delegate_consume(place_with_id={:?})", place_with_id);

View File

@ -5,6 +5,7 @@ use rustc_data_structures::{
};
use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
use rustc_middle::ty::{self, Ty};
use rustc_span::DUMMY_SP;
#[derive(Copy, Clone)]
pub enum DivergingFallbackBehavior {
@ -102,7 +103,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
// that field is only used for type fallback diagnostics.
for effect in unsolved_effects {
let expected = self.tcx.consts.true_;
let cause = self.misc(rustc_span::DUMMY_SP);
let cause = self.misc(DUMMY_SP);
match self.at(&cause, self.param_env).eq(DefineOpaqueTypes::Yes, expected, effect) {
Ok(InferOk { obligations, value: () }) => {
self.register_predicates(obligations);
@ -165,11 +166,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
};
debug!("fallback_if_possible(ty={:?}): defaulting to `{:?}`", ty, fallback);
let span = self
.infcx
.type_var_origin(ty)
.map(|origin| origin.span)
.unwrap_or(rustc_span::DUMMY_SP);
let span = self.infcx.type_var_origin(ty).map(|origin| origin.span).unwrap_or(DUMMY_SP);
self.demand_eqtype(span, ty, fallback);
self.fallback_has_occurred.set(true);
true

View File

@ -10,7 +10,7 @@ use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
use rustc_hir::{ExprKind, GenericArg, Node, QPath};
use rustc_hir::{ExprKind, GenericArg, HirId, Node, QPath};
use rustc_hir_analysis::hir_ty_lowering::errors::GenericsArgsErrExtend;
use rustc_hir_analysis::hir_ty_lowering::generics::{
check_generic_arg_count_for_call, lower_generic_args,
@ -47,7 +47,7 @@ use std::slice;
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// Produces warning on the given node, if the current point in the
/// function is unreachable, and there hasn't been another warning.
pub(in super::super) fn warn_if_unreachable(&self, id: hir::HirId, span: Span, kind: &str) {
pub(in super::super) fn warn_if_unreachable(&self, id: HirId, span: Span, kind: &str) {
// FIXME: Combine these two 'if' expressions into one once
// let chains are implemented
if let Diverges::Always { span: orig_span, custom_note } = self.diverges.get() {
@ -130,14 +130,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
format!("{self:p}")
}
pub fn local_ty(&self, span: Span, nid: hir::HirId) -> Ty<'tcx> {
pub fn local_ty(&self, span: Span, nid: HirId) -> Ty<'tcx> {
self.locals.borrow().get(&nid).cloned().unwrap_or_else(|| {
span_bug!(span, "no type for local variable {}", self.tcx.hir().node_to_string(nid))
})
}
#[inline]
pub fn write_ty(&self, id: hir::HirId, ty: Ty<'tcx>) {
pub fn write_ty(&self, id: HirId, ty: Ty<'tcx>) {
debug!("write_ty({:?}, {:?}) in fcx {}", id, self.resolve_vars_if_possible(ty), self.tag());
let mut typeck = self.typeck_results.borrow_mut();
let mut node_ty = typeck.node_types_mut();
@ -161,7 +161,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub fn write_field_index(
&self,
hir_id: hir::HirId,
hir_id: HirId,
index: FieldIdx,
nested_fields: Vec<(Ty<'tcx>, FieldIdx)>,
) {
@ -174,7 +174,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
#[instrument(level = "debug", skip(self))]
pub(in super::super) fn write_resolution(
&self,
hir_id: hir::HirId,
hir_id: HirId,
r: Result<(DefKind, DefId), ErrorGuaranteed>,
) {
self.typeck_results.borrow_mut().type_dependent_defs_mut().insert(hir_id, r);
@ -183,7 +183,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
#[instrument(level = "debug", skip(self))]
pub fn write_method_call_and_enforce_effects(
&self,
hir_id: hir::HirId,
hir_id: HirId,
span: Span,
method: MethodCallee<'tcx>,
) {
@ -192,7 +192,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.write_args(hir_id, method.args);
}
pub fn write_args(&self, node_id: hir::HirId, args: GenericArgsRef<'tcx>) {
pub fn write_args(&self, node_id: HirId, args: GenericArgsRef<'tcx>) {
if !args.is_empty() {
debug!("write_args({:?}, {:?}) in fcx {}", node_id, args, self.tag());
@ -210,7 +210,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
#[instrument(skip(self), level = "debug")]
pub fn write_user_type_annotation_from_args(
&self,
hir_id: hir::HirId,
hir_id: HirId,
def_id: DefId,
args: GenericArgsRef<'tcx>,
user_self_ty: Option<UserSelfTy<'tcx>>,
@ -230,7 +230,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
#[instrument(skip(self), level = "debug")]
pub fn write_user_type_annotation(
&self,
hir_id: hir::HirId,
hir_id: HirId,
canonical_user_type_annotation: CanonicalUserType<'tcx>,
) {
debug!("fcx {}", self.tag());
@ -464,7 +464,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
t.has_free_regions() || t.has_aliases() || t.has_infer_types()
}
pub fn node_ty(&self, id: hir::HirId) -> Ty<'tcx> {
pub fn node_ty(&self, id: HirId) -> Ty<'tcx> {
match self.typeck_results.borrow().node_types().get(id) {
Some(&t) => t,
None if let Some(e) = self.tainted_by_errors() => Ty::new_error(self.tcx, e),
@ -478,7 +478,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
pub fn node_ty_opt(&self, id: hir::HirId) -> Option<Ty<'tcx>> {
pub fn node_ty_opt(&self, id: HirId) -> Option<Ty<'tcx>> {
match self.typeck_results.borrow().node_types().get(id) {
Some(&t) => Some(t),
None if let Some(e) = self.tainted_by_errors() => Some(Ty::new_error(self.tcx, e)),
@ -742,7 +742,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self,
lang_item: hir::LangItem,
span: Span,
hir_id: hir::HirId,
hir_id: HirId,
) -> (Res, Ty<'tcx>) {
let def_id = self.tcx.require_lang_item(lang_item, Some(span));
let def_kind = self.tcx.def_kind(def_id);
@ -790,7 +790,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub fn resolve_ty_and_res_fully_qualified_call(
&self,
qpath: &'tcx QPath<'tcx>,
hir_id: hir::HirId,
hir_id: HirId,
span: Span,
args: Option<&'tcx [hir::Expr<'tcx>]>,
) -> (Res, Option<LoweredTy<'tcx>>, &'tcx [hir::PathSegment<'tcx>]) {
@ -984,7 +984,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// suggestion can be made, `None` otherwise.
pub fn get_fn_decl(
&self,
blk_id: hir::HirId,
blk_id: HirId,
) -> Option<(LocalDefId, &'tcx hir::FnDecl<'tcx>, bool)> {
// Get enclosing Fn, if it is a function or a trait method, unless there's a `loop` or
// `while` before reaching it, as block tail returns are not available in them.
@ -1080,7 +1080,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
res: Res,
span: Span,
path_span: Span,
hir_id: hir::HirId,
hir_id: HirId,
) -> (Ty<'tcx>, Res) {
let tcx = self.tcx;
@ -1450,7 +1450,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
span: Span,
def_id: DefId,
args: GenericArgsRef<'tcx>,
hir_id: hir::HirId,
hir_id: HirId,
) {
self.add_required_obligations_with_code(span, def_id, args, |idx, span| {
if span.is_dummy() {
@ -1541,7 +1541,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub(in super::super) fn with_breakable_ctxt<F: FnOnce() -> R, R>(
&self,
id: hir::HirId,
id: HirId,
ctxt: BreakableCtxt<'tcx>,
f: F,
) -> (BreakableCtxt<'tcx>, R) {
@ -1580,7 +1580,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
/// Returns `true` if an expression is contained inside the LHS of an assignment expression.
pub(in super::super) fn expr_in_place(&self, mut expr_id: hir::HirId) -> bool {
pub(in super::super) fn expr_in_place(&self, mut expr_id: HirId) -> bool {
let mut contained_in_place = false;
while let hir::Node::Expr(parent_expr) = self.tcx.parent_hir_node(expr_id) {

View File

@ -2,7 +2,7 @@ use crate::FnCtxt;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_infer::{infer::type_variable::TypeVariableOriginKind, traits::ObligationCauseCode};
use rustc_infer::traits::ObligationCauseCode;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
use rustc_span::{symbol::kw, Span};
use rustc_trait_selection::traits;
@ -340,7 +340,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
type Result = ControlFlow<ty::GenericArg<'tcx>>;
fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
if let Some(origin) = self.0.type_var_origin(ty)
&& let TypeVariableOriginKind::TypeParameterDefinition(_, def_id) = origin.kind
&& let Some(def_id) = origin.param_def_id
&& let generics = self.0.tcx.generics_of(self.1)
&& let Some(index) = generics.param_def_id_to_index(self.0.tcx, def_id)
&& let Some(arg) =

View File

@ -24,14 +24,14 @@ use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor;
use rustc_hir::{ExprKind, Node, QPath};
use rustc_hir::{ExprKind, HirId, Node, QPath};
use rustc_hir_analysis::check::intrinsicck::InlineAsmCtxt;
use rustc_hir_analysis::check::potentially_plural_count;
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
use rustc_hir_analysis::structured_errors::StructuredDiag;
use rustc_index::IndexVec;
use rustc_infer::infer::error_reporting::{FailureCode, ObligationCauseExt};
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::type_variable::TypeVariableOrigin;
use rustc_infer::infer::TypeTrace;
use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
use rustc_middle::traits::ObligationCauseCode::ExprBindingObligation;
@ -1489,7 +1489,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub fn check_struct_path(
&self,
qpath: &QPath<'tcx>,
hir_id: hir::HirId,
hir_id: HirId,
) -> Result<(&'tcx ty::VariantDef, Ty<'tcx>), ErrorGuaranteed> {
let path_span = qpath.span();
let (def, ty) = self.finish_resolving_struct_path(qpath, path_span, hir_id);
@ -1554,7 +1554,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub fn check_decl_initializer(
&self,
hir_id: hir::HirId,
hir_id: HirId,
pat: &'tcx hir::Pat<'tcx>,
init: &'tcx hir::Expr<'tcx>,
) -> Ty<'tcx> {
@ -1879,7 +1879,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty
}
fn parent_item_span(&self, id: hir::HirId) -> Option<Span> {
fn parent_item_span(&self, id: HirId) -> Option<Span> {
let node = self.tcx.hir_node_by_def_id(self.tcx.hir().get_parent_item(id).def_id);
match node {
Node::Item(&hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })
@ -1897,7 +1897,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// Given a function block's `HirId`, returns its `FnDecl` if it exists, or `None` otherwise.
pub(crate) fn get_parent_fn_decl(
&self,
blk_id: hir::HirId,
blk_id: HirId,
) -> Option<(&'tcx hir::FnDecl<'tcx>, Ident)> {
let parent = self.tcx.hir_node_by_def_id(self.tcx.hir().get_parent_item(blk_id).def_id);
self.get_node_fn_decl(parent).map(|(_, fn_decl, ident, _)| (fn_decl, ident))
@ -1939,12 +1939,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expr.span
}
fn overwrite_local_ty_if_err(
&self,
hir_id: hir::HirId,
pat: &'tcx hir::Pat<'tcx>,
ty: Ty<'tcx>,
) {
fn overwrite_local_ty_if_err(&self, hir_id: HirId, pat: &'tcx hir::Pat<'tcx>, ty: Ty<'tcx>) {
if let Err(guar) = ty.error_reported() {
struct OverwritePatternsWithError {
pat_hir_ids: Vec<hir::HirId>,
@ -1977,7 +1972,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self,
qpath: &QPath<'tcx>,
path_span: Span,
hir_id: hir::HirId,
hir_id: HirId,
) -> (Res, LoweredTy<'tcx>) {
match *qpath {
QPath::Resolved(ref maybe_qself, path) => {
@ -2184,7 +2179,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
[
callee_ty,
self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::MiscVariable,
param_def_id: None,
span: rustc_span::DUMMY_SP,
}),
],

View File

@ -16,8 +16,8 @@ use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
use rustc_infer::infer;
use rustc_infer::infer::error_reporting::sub_relations::SubRelations;
use rustc_infer::infer::error_reporting::TypeErrCtxt;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
use rustc_infer::infer::type_variable::TypeVariableOrigin;
use rustc_middle::infer::unify_key::ConstVariableOrigin;
use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitableExt};
use rustc_session::Session;
use rustc_span::symbol::Ident;
@ -236,10 +236,7 @@ impl<'a, 'tcx> HirTyLowerer<'tcx> for FnCtxt<'a, 'tcx> {
fn ty_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> {
match param {
Some(param) => self.var_for_def(span, param).as_type().unwrap(),
None => self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::TypeInference,
span,
}),
None => self.next_ty_var(TypeVariableOrigin { param_def_id: None, span }),
}
}
@ -258,10 +255,7 @@ impl<'a, 'tcx> HirTyLowerer<'tcx> for FnCtxt<'a, 'tcx> {
},
) => self.var_for_effect(param).as_const().unwrap(),
Some(param) => self.var_for_def(span, param).as_const().unwrap(),
None => self.next_const_var(
ty,
ConstVariableOrigin { kind: ConstVariableOriginKind::ConstInference, span },
),
None => self.next_const_var(ty, ConstVariableOrigin { span, param_def_id: None }),
}
}

View File

@ -71,7 +71,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expr: &'tcx hir::Expr<'tcx>,
expected: Ty<'tcx>,
found: Ty<'tcx>,
blk_id: hir::HirId,
blk_id: HirId,
) -> bool {
let expr = expr.peel_drop_temps();
let mut pointing_at_return_type = false;
@ -1031,7 +1031,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn_decl: &hir::FnDecl<'tcx>,
expected: Ty<'tcx>,
found: Ty<'tcx>,
id: hir::HirId,
id: HirId,
fn_id: LocalDefId,
) {
if !expected.is_unit() {
@ -1600,12 +1600,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
fn is_loop(&self, id: hir::HirId) -> bool {
fn is_loop(&self, id: HirId) -> bool {
let node = self.tcx.hir_node(id);
matches!(node, Node::Expr(Expr { kind: ExprKind::Loop(..), .. }))
}
fn is_local_statement(&self, id: hir::HirId) -> bool {
fn is_local_statement(&self, id: HirId) -> bool {
let node = self.tcx.hir_node(id);
matches!(node, Node::Stmt(Stmt { kind: StmtKind::Let(..), .. }))
}

View File

@ -1,8 +1,8 @@
use crate::FnCtxt;
use rustc_hir as hir;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::PatKind;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_hir::{HirId, PatKind};
use rustc_infer::infer::type_variable::TypeVariableOrigin;
use rustc_middle::ty::Ty;
use rustc_middle::ty::UserType;
use rustc_span::def_id::LocalDefId;
@ -33,7 +33,7 @@ impl<'a> DeclOrigin<'a> {
///
/// It must have a hir_id, as this is how we connect gather_locals to the check functions.
pub(super) struct Declaration<'a> {
pub hir_id: hir::HirId,
pub hir_id: HirId,
pub pat: &'a hir::Pat<'a>,
pub ty: Option<&'a hir::Ty<'a>>,
pub span: Span,
@ -48,8 +48,8 @@ impl<'a> From<&'a hir::LetStmt<'a>> for Declaration<'a> {
}
}
impl<'a> From<(&'a hir::LetExpr<'a>, hir::HirId)> for Declaration<'a> {
fn from((let_expr, hir_id): (&'a hir::LetExpr<'a>, hir::HirId)) -> Self {
impl<'a> From<(&'a hir::LetExpr<'a>, HirId)> for Declaration<'a> {
fn from((let_expr, hir_id): (&'a hir::LetExpr<'a>, HirId)) -> Self {
let hir::LetExpr { pat, ty, span, init, is_recovered: _ } = *let_expr;
Declaration { hir_id, pat, ty, span, init: Some(init), origin: DeclOrigin::LetExpr }
}
@ -60,7 +60,7 @@ pub(super) struct GatherLocalsVisitor<'a, 'tcx> {
// parameters are special cases of patterns, but we want to handle them as
// *distinct* cases. so track when we are hitting a pattern *within* an fn
// parameter.
outermost_fn_param_pat: Option<(Span, hir::HirId)>,
outermost_fn_param_pat: Option<(Span, HirId)>,
}
impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
@ -68,14 +68,11 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
Self { fcx, outermost_fn_param_pat: None }
}
fn assign(&mut self, span: Span, nid: hir::HirId, ty_opt: Option<Ty<'tcx>>) -> Ty<'tcx> {
fn assign(&mut self, span: Span, nid: HirId, ty_opt: Option<Ty<'tcx>>) -> Ty<'tcx> {
match ty_opt {
None => {
// Infer the variable's type.
let var_ty = self.fcx.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::TypeInference,
span,
});
let var_ty = self.fcx.next_ty_var(TypeVariableOrigin { param_def_id: None, span });
self.fcx.locals.borrow_mut().insert(nid, var_ty);
var_ty
}

View File

@ -56,11 +56,11 @@ use rustc_data_structures::unord::UnordSet;
use rustc_errors::{codes::*, struct_span_code_err, ErrorGuaranteed};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::{Map, Visitor};
use rustc_hir::{HirIdMap, Node};
use rustc_hir::intravisit::Visitor;
use rustc_hir::{HirId, HirIdMap, Node};
use rustc_hir_analysis::check::check_abi;
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::type_variable::TypeVariableOrigin;
use rustc_infer::traits::{ObligationCauseCode, ObligationInspector, WellFormedLoc};
use rustc_middle::query::Providers;
use rustc_middle::traits;
@ -261,10 +261,7 @@ fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Opti
tcx.impl_trait_ref(item.container_id(tcx)).unwrap().instantiate_identity().args;
Some(tcx.type_of(trait_item).instantiate(tcx, args))
} else {
Some(fcx.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::TypeInference,
span,
}))
Some(fcx.next_ty_var(TypeVariableOrigin { span, param_def_id: None }))
}
} else if let Node::AnonConst(_) = node {
let id = tcx.local_def_id_to_hir_id(def_id);
@ -272,10 +269,7 @@ fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Opti
Node::Ty(&hir::Ty { kind: hir::TyKind::Typeof(ref anon_const), span, .. })
if anon_const.hir_id == id =>
{
Some(fcx.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::TypeInference,
span,
}))
Some(fcx.next_ty_var(TypeVariableOrigin { span, param_def_id: None }))
}
Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), span, .. })
| Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm(asm), span, .. }) => {
@ -285,10 +279,7 @@ fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Opti
Some(fcx.next_int_var())
}
hir::InlineAsmOperand::SymFn { anon_const } if anon_const.hir_id == id => {
Some(fcx.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::MiscVariable,
span,
}))
Some(fcx.next_ty_var(TypeVariableOrigin { span, param_def_id: None }))
}
_ => None,
})
@ -348,13 +339,13 @@ pub struct EnclosingBreakables<'tcx> {
}
impl<'tcx> EnclosingBreakables<'tcx> {
fn find_breakable(&mut self, target_id: hir::HirId) -> &mut BreakableCtxt<'tcx> {
fn find_breakable(&mut self, target_id: HirId) -> &mut BreakableCtxt<'tcx> {
self.opt_find_breakable(target_id).unwrap_or_else(|| {
bug!("could not find enclosing breakable with id {}", target_id);
})
}
fn opt_find_breakable(&mut self, target_id: hir::HirId) -> Option<&mut BreakableCtxt<'tcx>> {
fn opt_find_breakable(&mut self, target_id: HirId) -> Option<&mut BreakableCtxt<'tcx>> {
match self.by_id.get(&target_id) {
Some(ix) => Some(&mut self.stack[*ix]),
None => None,
@ -374,7 +365,7 @@ fn report_unexpected_variant_res(
Res::Def(DefKind::Variant, _) => "struct variant",
_ => res.descr(),
};
let path_str = rustc_hir_pretty::qpath_to_string(qpath);
let path_str = rustc_hir_pretty::qpath_to_string(&tcx, qpath);
let err = tcx
.dcx()
.struct_span_err(span, format!("expected {expected}, found {res_descr} `{path_str}`"))
@ -436,28 +427,6 @@ fn fatally_break_rust(tcx: TyCtxt<'_>, span: Span) -> ! {
diag.emit()
}
pub fn lookup_method_for_diagnostic<'tcx>(
tcx: TyCtxt<'tcx>,
(def_id, hir_id): (LocalDefId, hir::HirId),
) -> Option<DefId> {
let root_ctxt = TypeckRootCtxt::new(tcx, def_id);
let param_env = tcx.param_env(def_id);
let fn_ctxt = FnCtxt::new(&root_ctxt, param_env, def_id);
let hir::Node::Expr(expr) = tcx.hir().hir_node(hir_id) else {
return None;
};
let hir::ExprKind::MethodCall(segment, rcvr, _, _) = expr.kind else {
return None;
};
let tables = tcx.typeck(def_id);
// The found `Self` type of the method call.
let possible_rcvr_ty = tables.node_type_opt(rcvr.hir_id)?;
fn_ctxt
.lookup_method_for_diagnostic(possible_rcvr_ty, segment, expr.span, expr, rcvr)
.ok()
.map(|method| method.def_id)
}
pub fn provide(providers: &mut Providers) {
method::provide(providers);
*providers = Providers {
@ -465,7 +434,6 @@ pub fn provide(providers: &mut Providers) {
diagnostic_only_typeck,
has_typeck_results,
used_trait_imports,
lookup_method_for_diagnostic: lookup_method_for_diagnostic,
..*providers
};
}

View File

@ -58,24 +58,24 @@ use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::def_id::LocalDefId;
use rustc_hir::pat_util::EnumerateAndAdjustIterator;
use rustc_hir::PatKind;
use rustc_hir::{HirId, PatKind};
use rustc_infer::infer::InferCtxt;
use rustc_span::Span;
use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
use rustc_trait_selection::infer::InferCtxtExt;
pub(crate) trait HirNode {
fn hir_id(&self) -> hir::HirId;
fn hir_id(&self) -> HirId;
}
impl HirNode for hir::Expr<'_> {
fn hir_id(&self) -> hir::HirId {
fn hir_id(&self) -> HirId {
self.hir_id
}
}
impl HirNode for hir::Pat<'_> {
fn hir_id(&self) -> hir::HirId {
fn hir_id(&self) -> HirId {
self.hir_id
}
}
@ -86,7 +86,7 @@ pub(crate) struct MemCategorizationContext<'a, 'tcx> {
infcx: &'a InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
body_owner: LocalDefId,
upvars: Option<&'tcx FxIndexMap<hir::HirId, hir::Upvar>>,
upvars: Option<&'tcx FxIndexMap<HirId, hir::Upvar>>,
}
pub(crate) type McResult<T> = Result<T, ()>;
@ -127,11 +127,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
self.infcx.tainted_by_errors().is_some()
}
fn resolve_type_vars_or_error(
&self,
id: hir::HirId,
ty: Option<Ty<'tcx>>,
) -> McResult<Ty<'tcx>> {
fn resolve_type_vars_or_error(&self, id: HirId, ty: Option<Ty<'tcx>>) -> McResult<Ty<'tcx>> {
match ty {
Some(ty) => {
let ty = self.resolve_vars_if_possible(ty);
@ -153,7 +149,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
}
}
pub(crate) fn node_ty(&self, hir_id: hir::HirId) -> McResult<Ty<'tcx>> {
pub(crate) fn node_ty(&self, hir_id: HirId) -> McResult<Ty<'tcx>> {
self.resolve_type_vars_or_error(hir_id, self.typeck_results.node_type_opt(hir_id))
}
@ -377,7 +373,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
#[instrument(level = "debug", skip(self, span), ret)]
pub(crate) fn cat_res(
&self,
hir_id: hir::HirId,
hir_id: HirId,
span: Span,
expr_ty: Ty<'tcx>,
res: Res,
@ -416,7 +412,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
/// environment and upvar reference as appropriate. Only regionck cares
/// about these dereferences, so we let it compute them as needed.
#[instrument(level = "debug", skip(self), ret)]
fn cat_upvar(&self, hir_id: hir::HirId, var_id: hir::HirId) -> McResult<PlaceWithHirId<'tcx>> {
fn cat_upvar(&self, hir_id: HirId, var_id: HirId) -> McResult<PlaceWithHirId<'tcx>> {
let closure_expr_def_id = self.body_owner;
let upvar_id = ty::UpvarId {
@ -429,7 +425,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
}
#[instrument(level = "debug", skip(self), ret)]
pub(crate) fn cat_rvalue(&self, hir_id: hir::HirId, expr_ty: Ty<'tcx>) -> PlaceWithHirId<'tcx> {
pub(crate) fn cat_rvalue(&self, hir_id: HirId, expr_ty: Ty<'tcx>) -> PlaceWithHirId<'tcx> {
PlaceWithHirId::new(hir_id, expr_ty, PlaceBase::Rvalue, Vec::new())
}
@ -523,7 +519,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
fn variant_index_for_adt(
&self,
qpath: &hir::QPath<'_>,
pat_hir_id: hir::HirId,
pat_hir_id: HirId,
span: Span,
) -> McResult<VariantIdx> {
let res = self.typeck_results.qpath_res(qpath, pat_hir_id);
@ -556,7 +552,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
/// Here `pat_hir_id` is the HirId of the pattern itself.
fn total_fields_in_adt_variant(
&self,
pat_hir_id: hir::HirId,
pat_hir_id: HirId,
variant_index: VariantIdx,
span: Span,
) -> McResult<usize> {
@ -573,7 +569,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
/// Returns the total number of fields in a tuple used within a Tuple pattern.
/// Here `pat_hir_id` is the HirId of the pattern itself.
fn total_fields_in_tuple(&self, pat_hir_id: hir::HirId, span: Span) -> McResult<usize> {
fn total_fields_in_tuple(&self, pat_hir_id: HirId, span: Span) -> McResult<usize> {
let ty = self.typeck_results.node_type(pat_hir_id);
match ty.kind() {
ty::Tuple(args) => Ok(args.len()),

View File

@ -173,7 +173,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
let Some((ty, n)) = autoderef.nth(pick.autoderefs) else {
return Ty::new_error_with_message(
self.tcx,
rustc_span::DUMMY_SP,
DUMMY_SP,
format!("failed autoderef {}", pick.autoderefs),
);
};
@ -608,7 +608,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
let span = predicates
.iter()
.find_map(|(p, span)| if p == pred { Some(span) } else { None })
.unwrap_or(rustc_span::DUMMY_SP);
.unwrap_or(DUMMY_SP);
Some((trait_pred, span))
}
_ => None,

View File

@ -7,8 +7,8 @@ use hir::HirId;
use hir::ItemKind;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_middle::ty::{Adt, Array, Ref, Ty};
use rustc_infer::infer::type_variable::TypeVariableOrigin;
use rustc_middle::ty::{self, Ty};
use rustc_session::lint::builtin::RUST_2021_PRELUDE_COLLISIONS;
use rustc_span::symbol::kw::{Empty, Underscore};
use rustc_span::symbol::{sym, Ident};
@ -44,7 +44,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// but `[T; N].into_iter()` doesn't resolve to IntoIterator::into_iter
// before Rust 2021, which results in the same problem.
// It is only a problem for arrays.
sym::into_iter if let Array(..) = self_ty.kind() => {
sym::into_iter if let ty::Array(..) = self_ty.kind() => {
// In this case, it wasn't really a prelude addition that was the problem.
// Instead, the problem is that the array-into_iter hack will no longer apply in Rust 2021.
rustc_lint::ARRAY_INTO_ITER
@ -64,7 +64,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pick.autoref_or_ptr_adjustment,
Some(probe::AutorefOrPtrAdjustment::Autoref { .. })
)
&& matches!(self_ty.kind(), Ref(..))
&& matches!(self_ty.kind(), ty::Ref(..))
{
return;
}
@ -218,10 +218,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// If we know it does not, we don't need to warn.
if method_name.name == sym::from_iter {
if let Some(trait_def_id) = self.tcx.get_diagnostic_item(sym::FromIterator) {
let any_type = self.infcx.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::MiscVariable,
span,
});
let any_type =
self.infcx.next_ty_var(TypeVariableOrigin { param_def_id: None, span });
if !self
.infcx
.type_implements_trait(trait_def_id, [self_ty, any_type], self.param_env)
@ -280,7 +278,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// the user has written the self type with generics already which we (naively) do by looking
// for a "<" in `self_ty_name`.
if !self_ty_name.contains('<') {
if let Adt(def, _) = self_ty.kind() {
if let ty::Adt(def, _) = self_ty.kind() {
let generics = self.tcx.generics_of(def.did());
if !generics.params.is_empty() {
let counts = generics.own_counts();

View File

@ -8,6 +8,7 @@ use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::HirId;
use rustc_hir_analysis::autoderef::{self, Autoderef};
use rustc_infer::infer::canonical::OriginalQueryValues;
use rustc_infer::infer::canonical::{Canonical, QueryResponse};
@ -86,7 +87,7 @@ pub(crate) struct ProbeContext<'a, 'tcx> {
Vec<(ty::Predicate<'tcx>, Option<ty::Predicate<'tcx>>, Option<ObligationCause<'tcx>>)>,
>,
scope_expr_id: hir::HirId,
scope_expr_id: HirId,
}
impl<'a, 'tcx> Deref for ProbeContext<'a, 'tcx> {
@ -263,7 +264,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
mode: Mode,
return_type: Ty<'tcx>,
self_ty: Ty<'tcx>,
scope_expr_id: hir::HirId,
scope_expr_id: HirId,
candidate_filter: impl Fn(&ty::AssocItem) -> bool,
) -> Vec<ty::AssocItem> {
let method_names = self
@ -307,7 +308,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return_type: Option<Ty<'tcx>>,
is_suggestion: IsSuggestion,
self_ty: Ty<'tcx>,
scope_expr_id: hir::HirId,
scope_expr_id: HirId,
scope: ProbeScope,
) -> PickResult<'tcx> {
self.probe_op(
@ -331,7 +332,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return_type: Option<Ty<'tcx>>,
is_suggestion: IsSuggestion,
self_ty: Ty<'tcx>,
scope_expr_id: hir::HirId,
scope_expr_id: HirId,
scope: ProbeScope,
) -> Vec<Candidate<'tcx>> {
self.probe_op(
@ -362,7 +363,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return_type: Option<Ty<'tcx>>,
is_suggestion: IsSuggestion,
self_ty: Ty<'tcx>,
scope_expr_id: hir::HirId,
scope_expr_id: HirId,
scope: ProbeScope,
op: OP,
) -> Result<R, MethodError<'tcx>>
@ -589,7 +590,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
return_type: Option<Ty<'tcx>>,
orig_steps_var_values: &'a OriginalQueryValues<'tcx>,
steps: &'tcx [CandidateStep<'tcx>],
scope_expr_id: hir::HirId,
scope_expr_id: HirId,
) -> ProbeContext<'a, 'tcx> {
ProbeContext {
fcx,
@ -1381,7 +1382,7 @@ impl<'tcx> Pick<'tcx> {
&self,
tcx: TyCtxt<'tcx>,
span: Span,
scope_expr_id: hir::HirId,
scope_expr_id: HirId,
) {
if self.unstable_candidates.is_empty() {
return;
@ -1696,7 +1697,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
if let ProbeResult::Match = result
&& self
.at(&ObligationCause::dummy(), self.param_env)
.sup(DefineOpaqueTypes::No, return_ty, xform_ret_ty)
.sup(DefineOpaqueTypes::Yes, return_ty, xform_ret_ty)
.is_err()
{
result = ProbeResult::BadReturnType;

View File

@ -22,12 +22,8 @@ use rustc_hir::lang_items::LangItem;
use rustc_hir::PatKind::Binding;
use rustc_hir::PathSegment;
use rustc_hir::{ExprKind, Node, QPath};
use rustc_infer::infer::{
self,
type_variable::{TypeVariableOrigin, TypeVariableOriginKind},
RegionVariableOrigin,
};
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
use rustc_infer::infer::{self, type_variable::TypeVariableOrigin, RegionVariableOrigin};
use rustc_middle::infer::unify_key::ConstVariableOrigin;
use rustc_middle::ty::fast_reject::DeepRejectCtxt;
use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
use rustc_middle::ty::print::{with_crate_prefix, with_forced_trimmed_paths};
@ -82,13 +78,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let trait_ref = ty::TraitRef::new(
tcx,
fn_once,
[
ty,
self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::MiscVariable,
span,
}),
],
[ty, self.next_ty_var(TypeVariableOrigin { param_def_id: None, span })],
);
let poly_trait_ref = ty::Binder::dummy(trait_ref);
let obligation = Obligation::misc(
@ -1271,7 +1261,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.map(|expr| {
self.node_ty_opt(expr.hir_id).unwrap_or_else(|| {
self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::MiscVariable,
param_def_id: None,
span: expr.span,
})
})
@ -1854,23 +1844,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
has_unsuggestable_args = true;
match arg.unpack() {
GenericArgKind::Lifetime(_) => self
.next_region_var(RegionVariableOrigin::MiscVariable(
rustc_span::DUMMY_SP,
))
.next_region_var(RegionVariableOrigin::MiscVariable(DUMMY_SP))
.into(),
GenericArgKind::Type(_) => self
.next_ty_var(TypeVariableOrigin {
span: rustc_span::DUMMY_SP,
kind: TypeVariableOriginKind::MiscVariable,
span: DUMMY_SP,
param_def_id: None,
})
.into(),
GenericArgKind::Const(arg) => self
.next_const_var(
arg.ty(),
ConstVariableOrigin {
span: rustc_span::DUMMY_SP,
kind: ConstVariableOriginKind::MiscVariable,
},
ConstVariableOrigin { span: DUMMY_SP, param_def_id: None },
)
.into(),
}
@ -2768,7 +2753,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let SelfSource::QPath(ty) = self_source else {
return;
};
for (deref_ty, _) in self.autoderef(rustc_span::DUMMY_SP, rcvr_ty).skip(1) {
for (deref_ty, _) in self.autoderef(DUMMY_SP, rcvr_ty).skip(1) {
if let Ok(pick) = self.probe_for_name(
Mode::Path,
item_name,

View File

@ -7,7 +7,7 @@ use rustc_ast as ast;
use rustc_data_structures::packed::Pu128;
use rustc_errors::{codes::*, struct_span_code_err, Applicability, Diag};
use rustc_hir as hir;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::type_variable::TypeVariableOrigin;
use rustc_infer::traits::ObligationCauseCode;
use rustc_middle::ty::adjustment::{
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability,
@ -219,10 +219,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// e.g., adding `&'a T` and `&'b T`, given `&'x T: Add<&'x T>`, will result
// in `&'a T <: &'x T` and `&'b T <: &'x T`, instead of `'a = 'b = 'x`.
let lhs_ty = self.check_expr(lhs_expr);
let fresh_var = self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::MiscVariable,
span: lhs_expr.span,
});
let fresh_var = self
.next_ty_var(TypeVariableOrigin { param_def_id: None, span: lhs_expr.span });
self.demand_coerce(lhs_expr, lhs_ty, fresh_var, Some(rhs_expr), AllowTwoPhase::No)
}
IsAssign::Yes => {
@ -241,10 +239,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// using this variable as the expected type, which sometimes lets
// us do better coercions than we would be able to do otherwise,
// particularly for things like `String + &String`.
let rhs_ty_var = self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::MiscVariable,
span: rhs_expr.span,
});
let rhs_ty_var =
self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: rhs_expr.span });
let result = self.lookup_op_method(
(lhs_expr, lhs_ty),

View File

@ -9,9 +9,10 @@ use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::pat_util::EnumerateAndAdjustIterator;
use rustc_hir::{self as hir, BindingAnnotation, ByRef, HirId, Mutability, Pat, PatKind};
use rustc_infer::infer;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::type_variable::TypeVariableOrigin;
use rustc_lint as lint;
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::{self, Adt, Ty, TypeVisitableExt};
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::hygiene::DesugaringKind;
@ -79,6 +80,7 @@ struct TopInfo<'tcx> {
#[derive(Copy, Clone)]
struct PatInfo<'tcx, 'a> {
binding_mode: BindingAnnotation,
max_ref_mutbl: Mutability,
top_info: TopInfo<'tcx>,
decl_origin: Option<DeclOrigin<'a>>,
@ -160,8 +162,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
decl_origin: Option<DeclOrigin<'tcx>>,
) {
let info = TopInfo { expected, origin_expr, span };
let pat_info =
PatInfo { binding_mode: INITIAL_BM, top_info: info, decl_origin, current_depth: 0 };
let pat_info = PatInfo {
binding_mode: INITIAL_BM,
max_ref_mutbl: Mutability::Mut,
top_info: info,
decl_origin,
current_depth: 0,
};
self.check_pat(pat, expected, pat_info);
}
@ -172,7 +179,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// Conversely, inside this module, `check_pat_top` should never be used.
#[instrument(level = "debug", skip(self, pat_info))]
fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'tcx, '_>) {
let PatInfo { binding_mode: def_bm, top_info: ti, current_depth, .. } = pat_info;
let PatInfo { binding_mode: def_bm, max_ref_mutbl, top_info: ti, current_depth, .. } =
pat_info;
let path_res = match &pat.kind {
PatKind::Path(qpath) => Some(
@ -181,10 +189,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
_ => None,
};
let adjust_mode = self.calc_adjust_mode(pat, path_res.map(|(res, ..)| res));
let (expected, def_bm, ref_pattern_already_consumed) =
self.calc_default_binding_mode(pat, expected, def_bm, adjust_mode);
let (expected, def_bm, max_ref_mutbl, ref_pattern_already_consumed) =
self.calc_default_binding_mode(pat, expected, def_bm, adjust_mode, max_ref_mutbl);
let pat_info = PatInfo {
binding_mode: def_bm,
max_ref_mutbl,
top_info: ti,
decl_origin: pat_info.decl_origin,
current_depth: current_depth + 1,
@ -289,16 +298,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected: Ty<'tcx>,
def_bm: BindingAnnotation,
adjust_mode: AdjustMode,
) -> (Ty<'tcx>, BindingAnnotation, bool) {
max_ref_mutbl: Mutability,
) -> (Ty<'tcx>, BindingAnnotation, Mutability, bool) {
if let ByRef::Yes(mutbl) = def_bm.0 {
debug_assert!(mutbl <= max_ref_mutbl);
}
match adjust_mode {
AdjustMode::Pass => (expected, def_bm, false),
AdjustMode::Reset => (expected, INITIAL_BM, false),
AdjustMode::ResetAndConsumeRef(mutbl) => {
(expected, INITIAL_BM, def_bm.0 == ByRef::Yes(mutbl))
AdjustMode::Pass => (expected, def_bm, max_ref_mutbl, false),
AdjustMode::Reset => (expected, INITIAL_BM, Mutability::Mut, false),
AdjustMode::ResetAndConsumeRef(ref_pat_mutbl) => {
let mutbls_match = def_bm.0 == ByRef::Yes(ref_pat_mutbl);
if pat.span.at_least_rust_2024() && self.tcx.features().ref_pat_eat_one_layer_2024 {
if mutbls_match {
debug!("consuming inherited reference");
(expected, INITIAL_BM, cmp::min(max_ref_mutbl, ref_pat_mutbl), true)
} else {
let (new_ty, new_bm, max_ref_mutbl) = if ref_pat_mutbl == Mutability::Mut {
self.peel_off_references(
pat,
expected,
def_bm,
Mutability::Not,
max_ref_mutbl,
)
} else {
(expected, def_bm.cap_ref_mutability(Mutability::Not), Mutability::Not)
};
(new_ty, new_bm, max_ref_mutbl, false)
}
} else {
(expected, INITIAL_BM, max_ref_mutbl, mutbls_match)
}
}
AdjustMode::Peel => {
let peeled = self.peel_off_references(pat, expected, def_bm);
(peeled.0, peeled.1, false)
let peeled =
self.peel_off_references(pat, expected, def_bm, Mutability::Mut, max_ref_mutbl);
(peeled.0, peeled.1, peeled.2, false)
}
}
}
@ -379,7 +414,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pat: &'tcx Pat<'tcx>,
expected: Ty<'tcx>,
mut def_bm: BindingAnnotation,
) -> (Ty<'tcx>, BindingAnnotation) {
max_peelable_mutability: Mutability,
mut max_ref_mutability: Mutability,
) -> (Ty<'tcx>, BindingAnnotation, Mutability) {
let mut expected = self.try_structurally_resolve_type(pat.span, expected);
// Peel off as many `&` or `&mut` from the scrutinee type as possible. For example,
// for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches
@ -390,7 +427,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
//
// See the examples in `ui/match-defbm*.rs`.
let mut pat_adjustments = vec![];
while let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind() {
while let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind()
&& inner_mutability <= max_peelable_mutability
{
debug!("inspecting {:?}", expected);
debug!("current discriminant is Ref, inserting implicit deref");
@ -410,6 +449,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
});
}
if pat.span.at_least_rust_2024() && self.tcx.features().ref_pat_eat_one_layer_2024 {
def_bm = def_bm.cap_ref_mutability(max_ref_mutability);
if def_bm.0 == ByRef::Yes(Mutability::Not) {
max_ref_mutability = Mutability::Not;
}
}
if !pat_adjustments.is_empty() {
debug!("default binding mode is now {:?}", def_bm);
self.typeck_results
@ -418,7 +464,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.insert(pat.hir_id, pat_adjustments);
}
(expected, def_bm)
(expected, def_bm, max_ref_mutability)
}
fn check_pat_lit(
@ -629,12 +675,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected: Ty<'tcx>,
pat_info: PatInfo<'tcx, '_>,
) -> Ty<'tcx> {
let PatInfo { binding_mode: def_bm, top_info: ti, .. } = pat_info;
let PatInfo { binding_mode: BindingAnnotation(def_br, _), top_info: ti, .. } = pat_info;
// Determine the binding mode...
let bm = match ba {
BindingAnnotation(ByRef::No, Mutability::Not) => def_bm,
_ => ba,
BindingAnnotation(ByRef::No, Mutability::Mut)
if !(pat.span.at_least_rust_2024()
&& self.tcx.features().mut_preserve_binding_mode_2024)
&& matches!(def_br, ByRef::Yes(_)) =>
{
// `mut x` resets the binding mode in edition <= 2021.
self.tcx.emit_node_span_lint(
lint::builtin::DEREFERENCING_MUT_BINDING,
pat.hir_id,
pat.span,
errors::DereferencingMutBinding { span: pat.span },
);
BindingAnnotation(ByRef::No, Mutability::Mut)
}
BindingAnnotation(ByRef::No, mutbl) => BindingAnnotation(def_br, mutbl),
BindingAnnotation(ByRef::Yes(_), _) => ba,
};
// ...and store it in a side table:
self.typeck_results.borrow_mut().pat_binding_modes_mut().insert(pat.hir_id, bm);
@ -743,7 +803,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
// Precondition: pat is a Ref(_) pattern
/// Precondition: pat is a `Ref(_)` pattern
fn borrow_pat_suggestion(&self, err: &mut Diag<'_>, pat: &Pat<'_>) {
let tcx = self.tcx;
if let PatKind::Ref(inner, mutbl) = pat.kind
@ -1046,7 +1106,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
_ => {
let (type_def_id, item_def_id) = match pat_ty.kind() {
Adt(def, _) => match res {
ty::Adt(def, _) => match res {
Res::Def(DefKind::Const, def_id) => (Some(def.did()), Some(def_id)),
_ => (None, None),
},
@ -1094,15 +1154,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected: Ty<'tcx>,
pat_info: PatInfo<'tcx, '_>,
) -> Ty<'tcx> {
let PatInfo { binding_mode: def_bm, top_info: ti, decl_origin, current_depth } = pat_info;
let tcx = self.tcx;
let on_error = |e| {
for pat in subpats {
self.check_pat(
pat,
Ty::new_error(tcx, e),
PatInfo { binding_mode: def_bm, top_info: ti, decl_origin, current_depth },
);
self.check_pat(pat, Ty::new_error(tcx, e), pat_info);
}
};
let report_unexpected_res = |res: Res| {
@ -1147,7 +1202,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let pat_ty = pat_ty.no_bound_vars().expect("expected fn type");
// Type-check the tuple struct pattern against the expected type.
let diag = self.demand_eqtype_pat_diag(pat.span, expected, pat_ty, ti);
let diag = self.demand_eqtype_pat_diag(pat.span, expected, pat_ty, pat_info.top_info);
let had_err = if let Some(err) = diag {
err.emit();
true
@ -1165,11 +1220,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) {
let field = &variant.fields[FieldIdx::from_usize(i)];
let field_ty = self.field_ty(subpat.span, field, args);
self.check_pat(
subpat,
field_ty,
PatInfo { binding_mode: def_bm, top_info: ti, decl_origin, current_depth },
);
self.check_pat(subpat, field_ty, pat_info);
self.tcx.check_stability(
variant.fields[FieldIdx::from_usize(i)].did,
@ -1365,13 +1416,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
let max_len = cmp::max(expected_len, elements.len());
let element_tys_iter = (0..max_len).map(|_| {
self.next_ty_var(
// FIXME: `MiscVariable` for now -- obtaining the span and name information
// from all tuple elements isn't trivial.
TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span },
)
});
let element_tys_iter =
(0..max_len).map(|_| self.next_ty_var(TypeVariableOrigin { param_def_id: None, span }));
let element_tys = tcx.mk_type_list_from_iter(element_tys_iter);
let pat_ty = Ty::new_tup(tcx, element_tys);
if let Some(err) = self.demand_eqtype_pat_diag(span, expected, pat_ty, pat_info.top_info) {
@ -1561,7 +1607,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
{
let has_shorthand_field_name = field_patterns.iter().any(|field| field.is_shorthand);
if has_shorthand_field_name {
let path = rustc_hir_pretty::qpath_to_string(qpath);
let path = rustc_hir_pretty::qpath_to_string(&self.tcx, qpath);
let mut err = struct_span_code_err!(
self.dcx(),
pat.span,
@ -1743,7 +1789,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return None;
}
let path = rustc_hir_pretty::qpath_to_string(qpath);
let path = rustc_hir_pretty::qpath_to_string(&self.tcx, qpath);
let mut err = struct_span_code_err!(
self.dcx(),
pat.span,
@ -1793,7 +1839,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
f
}
}
Err(_) => rustc_hir_pretty::pat_to_string(field.pat),
Err(_) => rustc_hir_pretty::pat_to_string(&self.tcx, field.pat),
}
})
.collect::<Vec<String>>()
@ -1997,10 +2043,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Ok(()) => {
// Here, `demand::subtype` is good enough, but I don't
// think any errors can be introduced by using `demand::eqtype`.
let inner_ty = self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::TypeInference,
span: inner.span,
});
let inner_ty =
self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: inner.span });
let box_ty = Ty::new_box(tcx, inner_ty);
self.demand_eqtype_pat(span, expected, box_ty, pat_info.top_info);
(box_ty, inner_ty)
@ -2063,61 +2107,70 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pat_info: PatInfo<'tcx, '_>,
consumed_inherited_ref: bool,
) -> Ty<'tcx> {
let tcx = self.tcx;
let expected = self.shallow_resolve(expected);
let (ref_ty, inner_ty) = match self.check_dereferenceable(pat.span, expected, inner) {
Ok(()) => {
// `demand::subtype` would be good enough, but using `eqtype` turns
// out to be equally general. See (note_1) for details.
if consumed_inherited_ref
&& pat.span.at_least_rust_2024()
&& self.tcx.features().ref_pat_eat_one_layer_2024
{
self.typeck_results.borrow_mut().skipped_ref_pats_mut().insert(pat.hir_id);
self.check_pat(inner, expected, pat_info);
expected
} else {
let tcx = self.tcx;
let expected = self.shallow_resolve(expected);
let (ref_ty, inner_ty) = match self.check_dereferenceable(pat.span, expected, inner) {
Ok(()) => {
// `demand::subtype` would be good enough, but using `eqtype` turns
// out to be equally general. See (note_1) for details.
// Take region, inner-type from expected type if we can,
// to avoid creating needless variables. This also helps with
// the bad interactions of the given hack detailed in (note_1).
debug!("check_pat_ref: expected={:?}", expected);
match *expected.kind() {
ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => (expected, r_ty),
_ => {
if consumed_inherited_ref && self.tcx.features().ref_pat_everywhere {
// We already matched against a match-ergonmics inserted reference,
// so we don't need to match against a reference from the original type.
// Save this infor for use in lowering later
self.typeck_results
.borrow_mut()
.skipped_ref_pats_mut()
.insert(pat.hir_id);
(expected, expected)
} else {
let inner_ty = self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::TypeInference,
span: inner.span,
});
let ref_ty = self.new_ref_ty(pat.span, mutbl, inner_ty);
debug!("check_pat_ref: demanding {:?} = {:?}", expected, ref_ty);
let err = self.demand_eqtype_pat_diag(
pat.span,
expected,
ref_ty,
pat_info.top_info,
);
// Take region, inner-type from expected type if we can,
// to avoid creating needless variables. This also helps with
// the bad interactions of the given hack detailed in (note_1).
debug!("check_pat_ref: expected={:?}", expected);
match *expected.kind() {
ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => (expected, r_ty),
_ => {
if consumed_inherited_ref && self.tcx.features().ref_pat_everywhere {
// We already matched against a match-ergonmics inserted reference,
// so we don't need to match against a reference from the original type.
// Save this infor for use in lowering later
self.typeck_results
.borrow_mut()
.skipped_ref_pats_mut()
.insert(pat.hir_id);
(expected, expected)
} else {
let inner_ty = self.next_ty_var(TypeVariableOrigin {
param_def_id: None,
span: inner.span,
});
let ref_ty = self.new_ref_ty(pat.span, mutbl, inner_ty);
debug!("check_pat_ref: demanding {:?} = {:?}", expected, ref_ty);
let err = self.demand_eqtype_pat_diag(
pat.span,
expected,
ref_ty,
pat_info.top_info,
);
// Look for a case like `fn foo(&foo: u32)` and suggest
// `fn foo(foo: &u32)`
if let Some(mut err) = err {
self.borrow_pat_suggestion(&mut err, pat);
err.emit();
// Look for a case like `fn foo(&foo: u32)` and suggest
// `fn foo(foo: &u32)`
if let Some(mut err) = err {
self.borrow_pat_suggestion(&mut err, pat);
err.emit();
}
(ref_ty, inner_ty)
}
(ref_ty, inner_ty)
}
}
}
}
Err(guar) => {
let err = Ty::new_error(tcx, guar);
(err, err)
}
};
self.check_pat(inner, inner_ty, pat_info);
ref_ty
Err(guar) => {
let err = Ty::new_error(tcx, guar);
(err, err)
}
};
self.check_pat(inner, inner_ty, pat_info);
ref_ty
}
}
/// Create a reference type with a fresh region variable.
@ -2138,8 +2191,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let tcx = self.tcx;
let len = before.len();
let ty_var_origin =
TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span };
let ty_var_origin = TypeVariableOrigin { param_def_id: None, span };
let inner_ty = self.next_ty_var(ty_var_origin);
Some(Ty::new_array(tcx, inner_ty, len.try_into().unwrap()))

View File

@ -4,7 +4,7 @@ use rustc_ast as ast;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir_analysis::autoderef::Autoderef;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::type_variable::TypeVariableOrigin;
use rustc_infer::infer::InferOk;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref, PointerCoercion};
use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
@ -147,10 +147,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// If some lookup succeeds, write callee into table and extract index/element
// type from the method signature.
// If some lookup succeeded, install method in table
let input_ty = self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::AutoDeref,
span: base_expr.span,
});
let input_ty =
self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: base_expr.span });
let method =
self.try_overloaded_place_op(expr.span, self_ty, &[input_ty], PlaceOp::Index);

View File

@ -3,7 +3,7 @@ use super::callee::DeferredCallResolution;
use rustc_data_structures::unord::{UnordMap, UnordSet};
use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::HirIdMap;
use rustc_hir::{HirId, HirIdMap};
use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::{self, Ty, TyCtxt};
@ -52,9 +52,9 @@ pub(crate) struct TypeckRootCtxt<'tcx> {
pub(super) deferred_cast_checks: RefCell<Vec<super::cast::CastCheck<'tcx>>>,
pub(super) deferred_transmute_checks: RefCell<Vec<(Ty<'tcx>, Ty<'tcx>, hir::HirId)>>,
pub(super) deferred_transmute_checks: RefCell<Vec<(Ty<'tcx>, Ty<'tcx>, HirId)>>,
pub(super) deferred_asm_checks: RefCell<Vec<(&'tcx hir::InlineAsm<'tcx>, hir::HirId)>>,
pub(super) deferred_asm_checks: RefCell<Vec<(&'tcx hir::InlineAsm<'tcx>, HirId)>>,
pub(super) deferred_coroutine_interiors: RefCell<Vec<(LocalDefId, hir::BodyId, Ty<'tcx>)>>,

View File

@ -38,6 +38,7 @@ use rustc_errors::{Applicability, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::HirId;
use rustc_infer::infer::UpvarRegion;
use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection, ProjectionKind};
use rustc_middle::mir::FakeReadCause;
@ -88,7 +89,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
enum UpvarMigrationInfo {
/// We previously captured all of `x`, but now we capture some sub-path.
CapturingPrecise { source_expr: Option<hir::HirId>, var_name: String },
CapturingPrecise { source_expr: Option<HirId>, var_name: String },
CapturingNothing {
// where the variable appears in the closure (but is not captured)
use_span: Span,
@ -131,7 +132,7 @@ struct MigrationLintNote {
/// Intermediate format to store the hir id of the root variable and a HashSet containing
/// information on why the root variable should be fully captured
struct NeededMigration {
var_hir_id: hir::HirId,
var_hir_id: HirId,
diagnostics_info: Vec<MigrationLintNote>,
}
@ -163,7 +164,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
#[instrument(skip(self, body), level = "debug")]
fn analyze_closure(
&self,
closure_hir_id: hir::HirId,
closure_hir_id: HirId,
span: Span,
body_id: hir::BodyId,
body: &'tcx hir::Body<'tcx>,
@ -1098,7 +1099,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn compute_2229_migrations_for_trait(
&self,
min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>,
var_hir_id: hir::HirId,
var_hir_id: HirId,
closure_clause: hir::CaptureBy,
) -> Option<FxIndexMap<UpvarMigrationInfo, UnordSet<&'static str>>> {
let auto_traits_def_id = [
@ -1210,7 +1211,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
closure_span: Span,
min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>,
closure_clause: hir::CaptureBy,
var_hir_id: hir::HirId,
var_hir_id: HirId,
) -> Option<FxIndexSet<UpvarMigrationInfo>> {
let ty = self.resolve_vars_if_possible(self.node_ty(var_hir_id));
@ -1650,7 +1651,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn place_for_root_variable(
&self,
closure_def_id: LocalDefId,
var_hir_id: hir::HirId,
var_hir_id: HirId,
) -> Place<'tcx> {
let upvar_id = ty::UpvarId::new(var_hir_id, closure_def_id);
@ -1881,7 +1882,7 @@ fn apply_capture_kind_on_capture_ty<'tcx>(
}
/// Returns the Span of where the value with the provided HirId would be dropped
fn drop_location_span(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> Span {
fn drop_location_span(tcx: TyCtxt<'_>, hir_id: HirId) -> Span {
let owner_id = tcx.hir().get_enclosing_scope(hir_id).unwrap();
let owner_node = tcx.hir_node(owner_id);
@ -1933,7 +1934,7 @@ struct InferBorrowKind<'tcx> {
/// Place { V1, [ProjectionKind::Field(Index=1, Variant=0)] } : CaptureKind { E2, MutableBorrow }
/// ```
capture_information: InferredCaptureInformation<'tcx>,
fake_reads: Vec<(Place<'tcx>, FakeReadCause, hir::HirId)>,
fake_reads: Vec<(Place<'tcx>, FakeReadCause, HirId)>,
}
impl<'tcx> euv::Delegate<'tcx> for InferBorrowKind<'tcx> {
@ -1941,7 +1942,7 @@ impl<'tcx> euv::Delegate<'tcx> for InferBorrowKind<'tcx> {
&mut self,
place: &PlaceWithHirId<'tcx>,
cause: FakeReadCause,
diag_expr_id: hir::HirId,
diag_expr_id: HirId,
) {
let PlaceBase::Upvar(_) = place.place.base else { return };
@ -1956,7 +1957,7 @@ impl<'tcx> euv::Delegate<'tcx> for InferBorrowKind<'tcx> {
}
#[instrument(skip(self), level = "debug")]
fn consume(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId) {
fn consume(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) {
let PlaceBase::Upvar(upvar_id) = place_with_id.place.base else { return };
assert_eq!(self.closure_def_id, upvar_id.closure_expr_id);
@ -1974,7 +1975,7 @@ impl<'tcx> euv::Delegate<'tcx> for InferBorrowKind<'tcx> {
fn borrow(
&mut self,
place_with_id: &PlaceWithHirId<'tcx>,
diag_expr_id: hir::HirId,
diag_expr_id: HirId,
bk: ty::BorrowKind,
) {
let PlaceBase::Upvar(upvar_id) = place_with_id.place.base else { return };
@ -2005,7 +2006,7 @@ impl<'tcx> euv::Delegate<'tcx> for InferBorrowKind<'tcx> {
}
#[instrument(skip(self), level = "debug")]
fn mutate(&mut self, assignee_place: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId) {
fn mutate(&mut self, assignee_place: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) {
self.borrow(assignee_place, diag_expr_id, ty::BorrowKind::MutBorrow);
}
}
@ -2192,14 +2193,14 @@ fn construct_capture_info_string<'tcx>(
format!("{place_str} -> {capture_kind_str}")
}
fn var_name(tcx: TyCtxt<'_>, var_hir_id: hir::HirId) -> Symbol {
fn var_name(tcx: TyCtxt<'_>, var_hir_id: HirId) -> Symbol {
tcx.hir().name(var_hir_id)
}
#[instrument(level = "debug", skip(tcx))]
fn should_do_rust_2021_incompatible_closure_captures_analysis(
tcx: TyCtxt<'_>,
closure_id: hir::HirId,
closure_id: HirId,
) -> bool {
if tcx.sess.at_least_rust_2021() {
return false;

View File

@ -7,6 +7,7 @@ use rustc_data_structures::unord::ExtendUnord;
use rustc_errors::{ErrorGuaranteed, StashKey};
use rustc_hir as hir;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::HirId;
use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion};
@ -134,7 +135,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
self.fcx.tcx
}
fn write_ty_to_typeck_results(&mut self, hir_id: hir::HirId, ty: Ty<'tcx>) {
fn write_ty_to_typeck_results(&mut self, hir_id: HirId, ty: Ty<'tcx>) {
debug!("write_ty_to_typeck_results({:?}, {:?})", hir_id, ty);
assert!(
!ty.has_infer() && !ty.has_placeholders() && !ty.has_free_regions(),
@ -461,7 +462,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
fcx_typeck_results.closure_kind_origins().items_in_stable_order();
for (local_id, origin) in fcx_closure_kind_origins {
let hir_id = hir::HirId { owner: common_hir_owner, local_id };
let hir_id = HirId { owner: common_hir_owner, local_id };
let place_span = origin.0;
let place = self.resolve(origin.1.clone(), &place_span);
self.typeck_results.closure_kind_origins_mut().insert(hir_id, (place_span, place));
@ -490,7 +491,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
let mut errors_buffer = Vec::new();
for (local_id, c_ty) in sorted_user_provided_types {
let hir_id = hir::HirId { owner: common_hir_owner, local_id };
let hir_id = HirId { owner: common_hir_owner, local_id };
if let ty::UserType::TypeOf(_, user_args) = c_ty.value {
// This is a unit-testing mechanism.
@ -513,7 +514,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
self.typeck_results.user_provided_types_mut().extend(
fcx_typeck_results.user_provided_types().items().map(|(local_id, c_ty)| {
let hir_id = hir::HirId { owner: common_hir_owner, local_id };
let hir_id = HirId { owner: common_hir_owner, local_id };
if cfg!(debug_assertions) && c_ty.has_infer() {
span_bug!(
@ -604,7 +605,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
}
}
fn visit_field_id(&mut self, hir_id: hir::HirId) {
fn visit_field_id(&mut self, hir_id: HirId) {
if let Some(index) = self.fcx.typeck_results.borrow_mut().field_indices_mut().remove(hir_id)
{
self.typeck_results.field_indices_mut().insert(hir_id, index);
@ -617,7 +618,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
}
#[instrument(skip(self, span), level = "debug")]
fn visit_node_id(&mut self, span: Span, hir_id: hir::HirId) {
fn visit_node_id(&mut self, span: Span, hir_id: HirId) {
// Export associated path extensions and method resolutions.
if let Some(def) =
self.fcx.typeck_results.borrow_mut().type_dependent_defs_mut().remove(hir_id)
@ -644,7 +645,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
}
#[instrument(skip(self, span), level = "debug")]
fn visit_adjustments(&mut self, span: Span, hir_id: hir::HirId) {
fn visit_adjustments(&mut self, span: Span, hir_id: HirId) {
let adjustment = self.fcx.typeck_results.borrow_mut().adjustments_mut().remove(hir_id);
match adjustment {
None => {
@ -660,7 +661,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
}
#[instrument(skip(self, span), level = "debug")]
fn visit_pat_adjustments(&mut self, span: Span, hir_id: hir::HirId) {
fn visit_pat_adjustments(&mut self, span: Span, hir_id: HirId) {
let adjustment = self.fcx.typeck_results.borrow_mut().pat_adjustments_mut().remove(hir_id);
match adjustment {
None => {
@ -691,7 +692,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
let fcx_liberated_fn_sigs = fcx_typeck_results.liberated_fn_sigs().items_in_stable_order();
for (local_id, &fn_sig) in fcx_liberated_fn_sigs {
let hir_id = hir::HirId { owner: common_hir_owner, local_id };
let hir_id = HirId { owner: common_hir_owner, local_id };
let fn_sig = self.resolve(fn_sig, &hir_id);
self.typeck_results.liberated_fn_sigs_mut().insert(hir_id, fn_sig);
}
@ -705,7 +706,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
let fcx_fru_field_types = fcx_typeck_results.fru_field_types().items_in_stable_order();
for (local_id, ftys) in fcx_fru_field_types {
let hir_id = hir::HirId { owner: common_hir_owner, local_id };
let hir_id = HirId { owner: common_hir_owner, local_id };
let ftys = self.resolve(ftys.clone(), &hir_id);
self.typeck_results.fru_field_types_mut().insert(hir_id, ftys);
}
@ -719,7 +720,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
for (local_id, &(container, ref indices)) in
fcx_typeck_results.offset_of_data().items_in_stable_order()
{
let hir_id = hir::HirId { owner: common_hir_owner, local_id };
let hir_id = HirId { owner: common_hir_owner, local_id };
let container = self.resolve(container, &hir_id);
self.typeck_results.offset_of_data_mut().insert(hir_id, (container, indices.clone()));
}
@ -754,7 +755,7 @@ impl Locatable for Span {
}
}
impl Locatable for hir::HirId {
impl Locatable for HirId {
fn to_span(&self, tcx: TyCtxt<'_>) -> Span {
tcx.hir().span(*self)
}

View File

@ -282,7 +282,7 @@ impl<'a, 'tcx> Trace<'a, 'tcx> {
{
let Trace { at, trace } = self;
debug_assert!(at.infcx.next_trait_solver());
let mut fields = at.infcx.combine_fields(trace, at.param_env, DefineOpaqueTypes::No);
let mut fields = at.infcx.combine_fields(trace, at.param_env, DefineOpaqueTypes::Yes);
fields
.equate(StructurallyRelateAliases::Yes)
.relate(a, b)

View File

@ -802,7 +802,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
const_var: ty::Const<'tcx>,
) -> ty::Const<'tcx> {
debug_assert!(
!self.infcx.is_some_and(|infcx| const_var != infcx.shallow_resolve(const_var))
!self.infcx.is_some_and(|infcx| const_var != infcx.shallow_resolve_const(const_var))
);
let var = self.canonical_var(info, const_var.into());
ty::Const::new_bound(self.tcx, self.binder_index, var, self.fold_ty(const_var.ty()))

View File

@ -21,8 +21,8 @@
//!
//! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html
use crate::infer::{ConstVariableOrigin, ConstVariableOriginKind};
use crate::infer::{InferCtxt, RegionVariableOrigin, TypeVariableOrigin, TypeVariableOriginKind};
use crate::infer::ConstVariableOrigin;
use crate::infer::{InferCtxt, RegionVariableOrigin, TypeVariableOrigin};
use rustc_index::IndexVec;
use rustc_middle::infer::unify_key::EffectVarValue;
use rustc_middle::ty::fold::TypeFoldable;
@ -115,7 +115,7 @@ impl<'tcx> InferCtxt<'tcx> {
CanonicalVarKind::Ty(ty_kind) => {
let ty = match ty_kind {
CanonicalTyVarKind::General(ui) => self.next_ty_var_in_universe(
TypeVariableOrigin { kind: TypeVariableOriginKind::MiscVariable, span },
TypeVariableOrigin { param_def_id: None, span },
universe_map(ui),
),
@ -148,7 +148,7 @@ impl<'tcx> InferCtxt<'tcx> {
CanonicalVarKind::Const(ui, ty) => self
.next_const_var_in_universe(
ty,
ConstVariableOrigin { kind: ConstVariableOriginKind::MiscVariable, span },
ConstVariableOrigin { param_def_id: None, span },
universe_map(ui),
)
.into(),

View File

@ -3,7 +3,7 @@ use crate::errors::{
SourceKindMultiSuggestion, SourceKindSubdiag,
};
use crate::infer::error_reporting::TypeErrCtxt;
use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use crate::infer::type_variable::TypeVariableOrigin;
use crate::infer::InferCtxt;
use rustc_errors::{codes::*, Diag, IntoDiagArg};
use rustc_hir as hir;
@ -13,16 +13,14 @@ use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{Body, Closure, Expr, ExprKind, FnRetTy, HirId, LetStmt, LocalSource};
use rustc_middle::hir::nested_filter;
use rustc_middle::infer::unify_key::{
ConstVariableOrigin, ConstVariableOriginKind, ConstVariableValue,
};
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableValue};
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer};
use rustc_middle::ty::{
self, GenericArg, GenericArgKind, GenericArgsRef, InferConst, IsSuggestable, Ty, TyCtxt,
TypeFoldable, TypeFolder, TypeSuperFoldable, TypeckResults,
};
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::symbol::{sym, Ident};
use rustc_span::{BytePos, Span, DUMMY_SP};
use std::borrow::Cow;
use std::iter;
@ -188,8 +186,11 @@ fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinte
let mut infcx_inner = infcx.inner.borrow_mut();
let ty_vars = infcx_inner.type_variables();
let var_origin = ty_vars.var_origin(ty_vid);
if let TypeVariableOriginKind::TypeParameterDefinition(name, def_id) = var_origin.kind
&& name != kw::SelfUpper
if let Some(def_id) = var_origin.param_def_id
// The `Self` param of a trait has the def-id of the trait,
// since it's a synthetic parameter.
&& infcx.tcx.def_kind(def_id) == DefKind::TyParam
&& let name = infcx.tcx.item_name(def_id)
&& !var_origin.span.from_expansion()
{
let generics = infcx.tcx.generics_of(infcx.tcx.parent(def_id));
@ -216,8 +217,8 @@ fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinte
None
}
ConstVariableValue::Unknown { origin, universe: _ } => {
if let ConstVariableOriginKind::ConstParameterDefinition(name, _) = origin.kind {
return Some(name);
if let Some(def_id) = origin.param_def_id {
Some(infcx.tcx.item_name(def_id))
} else {
None
}
@ -302,21 +303,18 @@ impl<'tcx> InferCtxt<'tcx> {
let mut inner = self.inner.borrow_mut();
let ty_vars = &inner.type_variables();
let var_origin = ty_vars.var_origin(ty_vid);
if let TypeVariableOriginKind::TypeParameterDefinition(name, def_id) =
var_origin.kind
if let Some(def_id) = var_origin.param_def_id
// The `Self` param of a trait has the def-id of the trait,
// since it's a synthetic parameter.
&& self.tcx.def_kind(def_id) == DefKind::TyParam
&& !var_origin.span.from_expansion()
{
if name != kw::SelfUpper && !var_origin.span.from_expansion() {
return InferenceDiagnosticsData {
name: name.to_string(),
span: Some(var_origin.span),
kind: UnderspecifiedArgKind::Type {
prefix: "type parameter".into(),
},
parent: InferenceDiagnosticsParentData::for_def_id(
self.tcx, def_id,
),
};
}
return InferenceDiagnosticsData {
name: self.tcx.item_name(def_id).to_string(),
span: Some(var_origin.span),
kind: UnderspecifiedArgKind::Type { prefix: "type parameter".into() },
parent: InferenceDiagnosticsParentData::for_def_id(self.tcx, def_id),
};
}
}
@ -341,11 +339,9 @@ impl<'tcx> InferCtxt<'tcx> {
}
ConstVariableValue::Unknown { origin, universe: _ } => origin,
};
if let ConstVariableOriginKind::ConstParameterDefinition(name, def_id) =
origin.kind
{
if let Some(def_id) = origin.param_def_id {
return InferenceDiagnosticsData {
name: name.to_string(),
name: self.tcx.item_name(def_id).to_string(),
span: Some(origin.span),
kind: UnderspecifiedArgKind::Const { is_parameter: true },
parent: InferenceDiagnosticsParentData::for_def_id(self.tcx, def_id),
@ -549,16 +545,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
GenericArgKind::Type(_) => self
.next_ty_var(TypeVariableOrigin {
span: DUMMY_SP,
kind: TypeVariableOriginKind::MiscVariable,
param_def_id: None,
})
.into(),
GenericArgKind::Const(arg) => self
.next_const_var(
arg.ty(),
ConstVariableOrigin {
span: DUMMY_SP,
kind: ConstVariableOriginKind::MiscVariable,
},
ConstVariableOrigin { span: DUMMY_SP, param_def_id: None },
)
.into(),
}
@ -576,10 +569,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}
}
InferSourceKind::FullyQualifiedMethodCall { receiver, successor, args, def_id } => {
let placeholder = Some(self.next_ty_var(TypeVariableOrigin {
span: DUMMY_SP,
kind: TypeVariableOriginKind::MiscVariable,
}));
let placeholder = Some(
self.next_ty_var(TypeVariableOrigin { span: DUMMY_SP, param_def_id: None }),
);
if let Some(args) = args.make_suggestable(self.infcx.tcx, true, placeholder) {
let mut printer = fmt_printer(self, Namespace::ValueNS);
printer.print_def_path(def_id, args).unwrap();
@ -613,10 +605,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}
}
InferSourceKind::ClosureReturn { ty, data, should_wrap_expr } => {
let placeholder = Some(self.next_ty_var(TypeVariableOrigin {
span: DUMMY_SP,
kind: TypeVariableOriginKind::MiscVariable,
}));
let placeholder = Some(
self.next_ty_var(TypeVariableOrigin { span: DUMMY_SP, param_def_id: None }),
);
if let Some(ty) = ty.make_suggestable(self.infcx.tcx, true, placeholder) {
let ty_info = ty_to_string(self, ty, None);
multi_suggestions.push(SourceKindMultiSuggestion::new_closure_return(

View File

@ -283,6 +283,7 @@ pub fn suggest_new_region_bound(
continue;
}
match fn_return.kind {
// FIXME(precise_captures): Suggest adding to `use<...>` list instead.
TyKind::OpaqueDef(item_id, _, _) => {
let item = tcx.hir().item(item_id);
let ItemKind::OpaqueTy(opaque) = &item.kind else {

View File

@ -30,7 +30,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues};
use rustc_middle::infer::unify_key::ConstVariableValue;
use rustc_middle::infer::unify_key::EffectVarValue;
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType};
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ToType};
use rustc_middle::infer::unify_key::{ConstVidKey, EffectVidKey};
use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult};
use rustc_middle::mir::ConstraintCategory;
@ -48,7 +48,7 @@ use rustc_span::Span;
use snapshot::undo_log::InferCtxtUndoLogs;
use std::cell::{Cell, RefCell};
use std::fmt;
use type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use type_variable::TypeVariableOrigin;
pub mod at;
pub mod canonical;
@ -945,14 +945,27 @@ impl<'tcx> InferCtxt<'tcx> {
(&ty::Infer(ty::TyVar(a_vid)), &ty::Infer(ty::TyVar(b_vid))) => {
return Err((a_vid, b_vid));
}
// We don't silently want to constrain hidden types here, so we assert that either one side is
// an infer var, so it'll get constrained to whatever the other side is, or there are no opaque
// types involved.
// We don't expect this to actually get hit, but if it does, we now at least know how to write
// a test for it.
(_, ty::Infer(ty::TyVar(_))) => {}
(ty::Infer(ty::TyVar(_)), _) => {}
_ if (r_a, r_b).has_opaque_types() => {
span_bug!(
cause.span(),
"opaque types got hidden types registered from within subtype predicate: {r_a:?} vs {r_b:?}"
)
}
_ => {}
}
self.enter_forall(predicate, |ty::SubtypePredicate { a_is_expected, a, b }| {
if a_is_expected {
Ok(self.at(cause, param_env).sub(DefineOpaqueTypes::No, a, b))
Ok(self.at(cause, param_env).sub(DefineOpaqueTypes::Yes, a, b))
} else {
Ok(self.at(cause, param_env).sup(DefineOpaqueTypes::No, b, a))
Ok(self.at(cause, param_env).sup(DefineOpaqueTypes::Yes, b, a))
}
})
}
@ -1111,13 +1124,7 @@ impl<'tcx> InferCtxt<'tcx> {
// as the generic parameters for the default, `(T, U)`.
let ty_var_id = self.inner.borrow_mut().type_variables().new_var(
self.universe(),
TypeVariableOrigin {
kind: TypeVariableOriginKind::TypeParameterDefinition(
param.name,
param.def_id,
),
span,
},
TypeVariableOrigin { param_def_id: Some(param.def_id), span },
);
Ty::new_var(self.tcx, ty_var_id).into()
@ -1126,13 +1133,7 @@ impl<'tcx> InferCtxt<'tcx> {
if is_host_effect {
return self.var_for_effect(param);
}
let origin = ConstVariableOrigin {
kind: ConstVariableOriginKind::ConstParameterDefinition(
param.name,
param.def_id,
),
span,
};
let origin = ConstVariableOrigin { param_def_id: Some(param.def_id), span };
let const_var_id = self
.inner
.borrow_mut()
@ -1253,19 +1254,76 @@ impl<'tcx> InferCtxt<'tcx> {
}
}
/// Resolve any type variables found in `value` -- but only one
/// level. So, if the variable `?X` is bound to some type
/// `Foo<?Y>`, then this would return `Foo<?Y>` (but `?Y` may
/// itself be bound to a type).
///
/// Useful when you only need to inspect the outermost level of
/// the type and don't care about nested types (or perhaps you
/// will be resolving them as well, e.g. in a loop).
pub fn shallow_resolve<T>(&self, value: T) -> T
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
value.fold_with(&mut ShallowResolver { infcx: self })
pub fn shallow_resolve(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
if let ty::Infer(v) = ty.kind() { self.fold_infer_ty(*v).unwrap_or(ty) } else { ty }
}
// This is separate from `shallow_resolve` to keep that method small and inlinable.
#[inline(never)]
fn fold_infer_ty(&self, v: InferTy) -> Option<Ty<'tcx>> {
match v {
ty::TyVar(v) => {
// Not entirely obvious: if `typ` is a type variable,
// it can be resolved to an int/float variable, which
// can then be recursively resolved, hence the
// recursion. Note though that we prevent type
// variables from unifying to other type variables
// directly (though they may be embedded
// structurally), and we prevent cycles in any case,
// so this recursion should always be of very limited
// depth.
//
// Note: if these two lines are combined into one we get
// dynamic borrow errors on `self.inner`.
let known = self.inner.borrow_mut().type_variables().probe(v).known();
known.map(|t| self.shallow_resolve(t))
}
ty::IntVar(v) => self
.inner
.borrow_mut()
.int_unification_table()
.probe_value(v)
.map(|v| v.to_type(self.tcx)),
ty::FloatVar(v) => self
.inner
.borrow_mut()
.float_unification_table()
.probe_value(v)
.map(|v| v.to_type(self.tcx)),
ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => None,
}
}
pub fn shallow_resolve_const(&self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
match ct.kind() {
ty::ConstKind::Infer(infer_ct) => match infer_ct {
InferConst::Var(vid) => self
.inner
.borrow_mut()
.const_unification_table()
.probe_value(vid)
.known()
.unwrap_or(ct),
InferConst::EffectVar(vid) => self
.inner
.borrow_mut()
.effect_unification_table()
.probe_value(vid)
.known()
.unwrap_or(ct),
InferConst::Fresh(_) => ct,
},
ty::ConstKind::Param(_)
| ty::ConstKind::Bound(_, _)
| ty::ConstKind::Placeholder(_)
| ty::ConstKind::Unevaluated(_)
| ty::ConstKind::Value(_)
| ty::ConstKind::Error(_)
| ty::ConstKind::Expr(_) => ct,
}
}
pub fn root_var(&self, var: ty::TyVid) -> ty::TyVid {
@ -1411,10 +1469,7 @@ impl<'tcx> InferCtxt<'tcx> {
.entry(bt.var)
.or_insert_with(|| {
self.infcx
.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::MiscVariable,
span: self.span,
})
.next_ty_var(TypeVariableOrigin { param_def_id: None, span: self.span })
.into()
})
.expect_ty()
@ -1426,10 +1481,7 @@ impl<'tcx> InferCtxt<'tcx> {
self.infcx
.next_const_var(
ty,
ConstVariableOrigin {
kind: ConstVariableOriginKind::MiscVariable,
span: self.span,
},
ConstVariableOrigin { param_def_id: None, span: self.span },
)
.into()
})
@ -1782,89 +1834,6 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for InferenceLiteralEraser<'tcx> {
}
}
struct ShallowResolver<'a, 'tcx> {
infcx: &'a InferCtxt<'tcx>,
}
impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ShallowResolver<'a, 'tcx> {
fn interner(&self) -> TyCtxt<'tcx> {
self.infcx.tcx
}
/// If `ty` is a type variable of some kind, resolve it one level
/// (but do not resolve types found in the result). If `typ` is
/// not a type variable, just return it unmodified.
#[inline]
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
if let ty::Infer(v) = ty.kind() { self.fold_infer_ty(*v).unwrap_or(ty) } else { ty }
}
fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
match ct.kind() {
ty::ConstKind::Infer(InferConst::Var(vid)) => self
.infcx
.inner
.borrow_mut()
.const_unification_table()
.probe_value(vid)
.known()
.unwrap_or(ct),
ty::ConstKind::Infer(InferConst::EffectVar(vid)) => self
.infcx
.inner
.borrow_mut()
.effect_unification_table()
.probe_value(vid)
.known()
.unwrap_or(ct),
_ => ct,
}
}
}
impl<'a, 'tcx> ShallowResolver<'a, 'tcx> {
// This is separate from `fold_ty` to keep that method small and inlinable.
#[inline(never)]
fn fold_infer_ty(&mut self, v: InferTy) -> Option<Ty<'tcx>> {
match v {
ty::TyVar(v) => {
// Not entirely obvious: if `typ` is a type variable,
// it can be resolved to an int/float variable, which
// can then be recursively resolved, hence the
// recursion. Note though that we prevent type
// variables from unifying to other type variables
// directly (though they may be embedded
// structurally), and we prevent cycles in any case,
// so this recursion should always be of very limited
// depth.
//
// Note: if these two lines are combined into one we get
// dynamic borrow errors on `self.inner`.
let known = self.infcx.inner.borrow_mut().type_variables().probe(v).known();
known.map(|t| self.fold_ty(t))
}
ty::IntVar(v) => self
.infcx
.inner
.borrow_mut()
.int_unification_table()
.probe_value(v)
.map(|v| v.to_type(self.infcx.tcx)),
ty::FloatVar(v) => self
.infcx
.inner
.borrow_mut()
.float_unification_table()
.probe_value(v)
.map(|v| v.to_type(self.infcx.tcx)),
ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => None,
}
}
}
impl<'tcx> TypeTrace<'tcx> {
pub fn span(&self) -> Span {
self.cause.span

View File

@ -1,4 +1,4 @@
use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use super::type_variable::TypeVariableOrigin;
use super::{DefineOpaqueTypes, InferResult};
use crate::errors::OpaqueHiddenTypeDiag;
use crate::infer::{InferCtxt, InferOk};
@ -65,13 +65,7 @@ impl<'tcx> InferCtxt<'tcx> {
let span = if span.contains(def_span) { def_span } else { span };
let code = traits::ObligationCauseCode::OpaqueReturnType(None);
let cause = ObligationCause::new(span, body_id, code);
// FIXME(compiler-errors): We probably should add a new TypeVariableOriginKind
// for opaque types, and then use that kind to fix the spans for type errors
// that we see later on.
let ty_var = self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::MiscVariable,
span,
});
let ty_var = self.next_ty_var(TypeVariableOrigin { param_def_id: None, span });
obligations.extend(
self.handle_opaque_type(ty, ty_var, &cause, param_env).unwrap().obligations,
);

View File

@ -3,7 +3,7 @@ use rustc_middle::ty::{self, Ty};
use crate::traits::{Obligation, PredicateObligation};
use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use super::type_variable::TypeVariableOrigin;
use super::InferCtxt;
impl<'tcx> InferCtxt<'tcx> {
@ -24,7 +24,7 @@ impl<'tcx> InferCtxt<'tcx> {
debug_assert!(!self.next_trait_solver());
let def_id = projection_ty.def_id;
let ty_var = self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::NormalizeProjectionType,
param_def_id: None,
span: self.tcx.def_span(def_id),
});
let projection = ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::Projection(

View File

@ -155,8 +155,8 @@ impl<'tcx> InferCtxt<'tcx> {
return Ok(a);
}
let a = self.shallow_resolve(a);
let b = self.shallow_resolve(b);
let a = self.shallow_resolve_const(a);
let b = self.shallow_resolve_const(b);
// We should never have to relate the `ty` field on `Const` as it is checked elsewhere that consts have the
// correct type for the generic param they are an argument for. However there have been a number of cases

View File

@ -1,7 +1,7 @@
use std::mem;
use super::StructurallyRelateAliases;
use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind, TypeVariableValue};
use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableValue};
use crate::infer::{InferCtxt, ObligationEmittingRelation, RegionVariableOrigin};
use rustc_data_structures::sso::SsoHashMap;
use rustc_data_structures::stack::ensure_sufficient_stack;
@ -352,7 +352,7 @@ impl<'tcx> Generalizer<'_, 'tcx> {
) -> Result<Ty<'tcx>, TypeError<'tcx>> {
if self.infcx.next_trait_solver() && !alias.has_escaping_bound_vars() {
return Ok(self.infcx.next_ty_var_in_universe(
TypeVariableOrigin { kind: TypeVariableOriginKind::MiscVariable, span: self.span },
TypeVariableOrigin { param_def_id: None, span: self.span },
self.for_universe,
));
}
@ -375,10 +375,7 @@ impl<'tcx> Generalizer<'_, 'tcx> {
debug!("generalization failure in alias");
Ok(self.infcx.next_ty_var_in_universe(
TypeVariableOrigin {
kind: TypeVariableOriginKind::MiscVariable,
span: self.span,
},
TypeVariableOrigin { param_def_id: None, span: self.span },
self.for_universe,
))
}

View File

@ -18,7 +18,7 @@
//! [lattices]: https://en.wikipedia.org/wiki/Lattice_(order)
use super::combine::ObligationEmittingRelation;
use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use crate::infer::type_variable::TypeVariableOrigin;
use crate::infer::{DefineOpaqueTypes, InferCtxt};
use crate::traits::ObligationCause;
@ -88,18 +88,14 @@ where
// iterate on the subtype obligations that are returned, but I
// think this suffices. -nmatsakis
(&ty::Infer(TyVar(..)), _) => {
let v = infcx.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::LatticeVariable,
span: this.cause().span,
});
let v = infcx
.next_ty_var(TypeVariableOrigin { param_def_id: None, span: this.cause().span });
this.relate_bound(v, b, a)?;
Ok(v)
}
(_, &ty::Infer(TyVar(..))) => {
let v = infcx.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::LatticeVariable,
span: this.cause().span,
});
let v = infcx
.next_ty_var(TypeVariableOrigin { param_def_id: None, span: this.cause().span });
this.relate_bound(v, a, b)?;
Ok(v)
}

View File

@ -12,21 +12,19 @@ use rustc_middle::ty::{self, Const, InferConst, Ty, TyCtxt, TypeFoldable};
/// useful for printing messages etc but also required at various
/// points for correctness.
pub struct OpportunisticVarResolver<'a, 'tcx> {
// The shallow resolver is used to resolve inference variables at every
// level of the type.
shallow_resolver: crate::infer::ShallowResolver<'a, 'tcx>,
infcx: &'a InferCtxt<'tcx>,
}
impl<'a, 'tcx> OpportunisticVarResolver<'a, 'tcx> {
#[inline]
pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self {
OpportunisticVarResolver { shallow_resolver: crate::infer::ShallowResolver { infcx } }
OpportunisticVarResolver { infcx }
}
}
impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for OpportunisticVarResolver<'a, 'tcx> {
fn interner(&self) -> TyCtxt<'tcx> {
TypeFolder::interner(&self.shallow_resolver)
self.infcx.tcx
}
#[inline]
@ -34,7 +32,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for OpportunisticVarResolver<'a, 'tcx> {
if !t.has_non_region_infer() {
t // micro-optimize -- if there is nothing in this type that this fold affects...
} else {
let t = self.shallow_resolver.fold_ty(t);
let t = self.infcx.shallow_resolve(t);
t.super_fold_with(self)
}
}
@ -43,7 +41,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for OpportunisticVarResolver<'a, 'tcx> {
if !ct.has_non_region_infer() {
ct // micro-optimize -- if there is nothing in this const that this fold affects...
} else {
let ct = self.shallow_resolver.fold_const(ct);
let ct = self.infcx.shallow_resolve_const(ct);
ct.super_fold_with(self)
}
}
@ -160,7 +158,7 @@ impl<'a, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for FullTypeResolver<'a, 'tcx> {
if !c.has_infer() {
Ok(c) // micro-optimize -- if there is nothing in this const that this fold affects...
} else {
let c = self.infcx.shallow_resolve(c);
let c = self.infcx.shallow_resolve_const(c);
match c.kind() {
ty::ConstKind::Infer(InferConst::Var(vid)) => {
return Err(FixupError::UnresolvedConst(vid));

View File

@ -1,4 +1,4 @@
use rustc_middle::infer::unify_key::{ConstVariableOriginKind, ConstVariableValue, ConstVidKey};
use rustc_middle::infer::unify_key::{ConstVariableValue, ConstVidKey};
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
use rustc_middle::ty::{self, ConstVid, FloatVid, IntVid, RegionVid, Ty, TyCtxt, TyVid};
@ -33,10 +33,9 @@ fn const_vars_since_snapshot<'tcx>(
range.start.vid..range.end.vid,
(range.start.index()..range.end.index())
.map(|index| match table.probe_value(ConstVid::from_u32(index)) {
ConstVariableValue::Known { value: _ } => ConstVariableOrigin {
kind: ConstVariableOriginKind::MiscVariable,
span: rustc_span::DUMMY_SP,
},
ConstVariableValue::Known { value: _ } => {
ConstVariableOrigin { param_def_id: None, span: rustc_span::DUMMY_SP }
}
ConstVariableValue::Unknown { origin, universe: _ } => origin,
})
.collect(),

View File

@ -2,7 +2,6 @@ use rustc_data_structures::undo_log::Rollback;
use rustc_hir::def_id::DefId;
use rustc_index::IndexVec;
use rustc_middle::ty::{self, Ty, TyVid};
use rustc_span::symbol::Symbol;
use rustc_span::Span;
use crate::infer::InferCtxtUndoLogs;
@ -37,30 +36,11 @@ pub struct TypeVariableTable<'a, 'tcx> {
#[derive(Copy, Clone, Debug)]
pub struct TypeVariableOrigin {
pub kind: TypeVariableOriginKind,
pub span: Span,
}
/// Reasons to create a type inference variable
#[derive(Copy, Clone, Debug)]
pub enum TypeVariableOriginKind {
MiscVariable,
NormalizeProjectionType,
TypeInference,
TypeParameterDefinition(Symbol, DefId),
/// One of the upvars or closure kind parameters in a `ClosureArgs`
/// (before it has been determined).
// FIXME(eddyb) distinguish upvar inference variables from the rest.
ClosureSynthetic,
AutoDeref,
AdjustmentType,
/// In type check, when we are type checking a function that
/// returns `-> dyn Foo`, we instantiate a type variable with the
/// return type for diagnostic purposes.
DynReturnFn,
LatticeVariable,
/// `DefId` of the type parameter this was instantiated for, if any.
///
/// This should only be used for diagnostics.
pub param_def_id: Option<DefId>,
}
#[derive(Clone)]

View File

@ -5,6 +5,7 @@ use rustc_ast::{LitKind, MetaItemKind};
use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_data_structures::defer;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::jobserver;
use rustc_data_structures::stable_hasher::StableHasher;
use rustc_data_structures::sync::Lrc;
use rustc_errors::registry::Registry;
@ -21,7 +22,7 @@ use rustc_session::config::{self, Cfg, CheckCfg, ExpectedValues, Input, OutFileN
use rustc_session::filesearch::{self, sysroot_candidates};
use rustc_session::parse::ParseSess;
use rustc_session::{lint, CompilerIO, EarlyDiagCtxt, Session};
use rustc_span::source_map::FileLoader;
use rustc_span::source_map::{FileLoader, RealFileLoader, SourceMapInputs};
use rustc_span::symbol::sym;
use rustc_span::FileName;
use std::path::PathBuf;
@ -323,6 +324,18 @@ pub struct Config {
pub expanded_args: Vec<String>,
}
/// Initialize jobserver before getting `jobserver::client` and `build_session`.
pub(crate) fn initialize_checked_jobserver(early_dcx: &EarlyDiagCtxt) {
jobserver::initialize_checked(|err| {
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
early_dcx
.early_struct_warn(err)
.with_note("the build environment is likely misconfigured")
.emit()
});
}
// JUSTIFICATION: before session exists, only config
#[allow(rustc::bad_opt_access)]
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
@ -334,20 +347,25 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
// Check jobserver before run_in_thread_pool_with_globals, which call jobserver::acquire_thread
let early_dcx = EarlyDiagCtxt::new(config.opts.error_format);
early_dcx.initialize_checked_jobserver();
initialize_checked_jobserver(&early_dcx);
crate::callbacks::setup_callbacks();
let sysroot = filesearch::materialize_sysroot(config.opts.maybe_sysroot.clone());
let target = config::build_target_config(&early_dcx, &config.opts, &sysroot);
let file_loader = config.file_loader.unwrap_or_else(|| Box::new(RealFileLoader));
let path_mapping = config.opts.file_path_mapping();
let hash_kind = config.opts.unstable_opts.src_hash_algorithm(&target);
util::run_in_thread_pool_with_globals(
config.opts.edition,
config.opts.unstable_opts.threads,
SourceMapInputs { file_loader, path_mapping, hash_kind },
|current_gcx| {
crate::callbacks::setup_callbacks();
// The previous `early_dcx` can't be reused here because it doesn't
// impl `Send`. Creating a new one is fine.
let early_dcx = EarlyDiagCtxt::new(config.opts.error_format);
let sysroot = filesearch::materialize_sysroot(config.opts.maybe_sysroot.clone());
let target = config::build_target_config(&early_dcx, &config.opts, &sysroot);
let codegen_backend = match config.make_codegen_backend {
None => util::get_codegen_backend(
&early_dcx,
@ -372,9 +390,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
config.opts.unstable_opts.translate_directionality_markers,
) {
Ok(bundle) => bundle,
Err(e) => {
early_dcx.early_fatal(format!("failed to load fluent bundle: {e}"));
}
Err(e) => early_dcx.early_fatal(format!("failed to load fluent bundle: {e}")),
};
let mut locale_resources = Vec::from(config.locale_resources);
@ -393,7 +409,6 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
config.registry.clone(),
locale_resources,
config.lint_caps,
config.file_loader,
target,
sysroot,
util::rustc_version_str().unwrap_or("unknown"),
@ -440,45 +455,43 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
current_gcx,
};
rustc_span::set_source_map(compiler.sess.psess.clone_source_map(), move || {
// There are two paths out of `f`.
// - Normal exit.
// - Panic, e.g. triggered by `abort_if_errors`.
//
// We must run `finish_diagnostics` in both cases.
let res = {
// If `f` panics, `finish_diagnostics` will run during
// unwinding because of the `defer`.
let mut guar = None;
let sess_abort_guard = defer(|| {
guar = compiler.sess.finish_diagnostics(&config.registry);
});
// There are two paths out of `f`.
// - Normal exit.
// - Panic, e.g. triggered by `abort_if_errors`.
//
// We must run `finish_diagnostics` in both cases.
let res = {
// If `f` panics, `finish_diagnostics` will run during
// unwinding because of the `defer`.
let mut guar = None;
let sess_abort_guard = defer(|| {
guar = compiler.sess.finish_diagnostics(&config.registry);
});
let res = f(&compiler);
let res = f(&compiler);
// If `f` doesn't panic, `finish_diagnostics` will run
// normally when `sess_abort_guard` is dropped.
drop(sess_abort_guard);
// If `f` doesn't panic, `finish_diagnostics` will run
// normally when `sess_abort_guard` is dropped.
drop(sess_abort_guard);
// If `finish_diagnostics` emits errors (e.g. stashed
// errors) we can't return an error directly, because the
// return type of this function is `R`, not `Result<R, E>`.
// But we need to communicate the errors' existence to the
// caller, otherwise the caller might mistakenly think that
// no errors occurred and return a zero exit code. So we
// abort (panic) instead, similar to if `f` had panicked.
if guar.is_some() {
compiler.sess.dcx().abort_if_errors();
}
res
};
let prof = compiler.sess.prof.clone();
prof.generic_activity("drop_compiler").run(move || drop(compiler));
// If `finish_diagnostics` emits errors (e.g. stashed
// errors) we can't return an error directly, because the
// return type of this function is `R`, not `Result<R, E>`.
// But we need to communicate the errors' existence to the
// caller, otherwise the caller might mistakenly think that
// no errors occurred and return a zero exit code. So we
// abort (panic) instead, similar to if `f` had panicked.
if guar.is_some() {
compiler.sess.dcx().abort_if_errors();
}
res
})
};
let prof = compiler.sess.prof.clone();
prof.generic_activity("drop_compiler").run(move || drop(compiler));
res
},
)
}

View File

@ -1,5 +1,5 @@
#![allow(rustc::bad_opt_access)]
use crate::interface::parse_cfg;
use crate::interface::{initialize_checked_jobserver, parse_cfg};
use rustc_data_structures::profiling::TimePassesFormat;
use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig};
use rustc_session::config::{
@ -16,6 +16,7 @@ use rustc_session::search_paths::SearchPath;
use rustc_session::utils::{CanonicalizedPath, NativeLib, NativeLibKind};
use rustc_session::{build_session, filesearch, getopts, CompilerIO, EarlyDiagCtxt, Session};
use rustc_span::edition::{Edition, DEFAULT_EDITION};
use rustc_span::source_map::{RealFileLoader, SourceMapInputs};
use rustc_span::symbol::sym;
use rustc_span::{FileName, SourceFileHashAlgorithm};
use rustc_target::spec::{CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, RelocModel};
@ -25,42 +26,52 @@ use std::num::NonZero;
use std::path::{Path, PathBuf};
use std::sync::Arc;
fn mk_session(matches: getopts::Matches) -> (Session, Cfg) {
fn sess_and_cfg<F>(args: &[&'static str], f: F)
where
F: FnOnce(Session, Cfg),
{
let mut early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default());
early_dcx.initialize_checked_jobserver();
initialize_checked_jobserver(&early_dcx);
let registry = registry::Registry::new(&[]);
let matches = optgroups().parse(args).unwrap();
let sessopts = build_session_options(&mut early_dcx, &matches);
let temps_dir = sessopts.unstable_opts.temps_dir.as_deref().map(PathBuf::from);
let io = CompilerIO {
input: Input::Str { name: FileName::Custom(String::new()), input: String::new() },
output_dir: None,
output_file: None,
temps_dir,
};
let sysroot = filesearch::materialize_sysroot(sessopts.maybe_sysroot.clone());
let target = rustc_session::config::build_target_config(&early_dcx, &sessopts, &sysroot);
let hash_kind = sessopts.unstable_opts.src_hash_algorithm(&target);
let sm_inputs = Some(SourceMapInputs {
file_loader: Box::new(RealFileLoader) as _,
path_mapping: sessopts.file_path_mapping(),
hash_kind,
});
let sess = build_session(
early_dcx,
sessopts,
io,
None,
registry,
vec![],
Default::default(),
None,
target,
sysroot,
"",
None,
Arc::default(),
Default::default(),
);
let cfg = parse_cfg(&sess.dcx(), matches.opt_strs("cfg"));
(sess, cfg)
rustc_span::create_session_globals_then(DEFAULT_EDITION, sm_inputs, || {
let temps_dir = sessopts.unstable_opts.temps_dir.as_deref().map(PathBuf::from);
let io = CompilerIO {
input: Input::Str { name: FileName::Custom(String::new()), input: String::new() },
output_dir: None,
output_file: None,
temps_dir,
};
let sess = build_session(
early_dcx,
sessopts,
io,
None,
registry::Registry::new(&[]),
vec![],
Default::default(),
target,
sysroot,
"",
None,
Arc::default(),
Default::default(),
);
let cfg = parse_cfg(&sess.dcx(), matches.opt_strs("cfg"));
let cfg = build_configuration(&sess, cfg);
f(sess, cfg)
});
}
fn new_public_extern_entry<S, I>(locations: I) -> ExternEntry
@ -125,21 +136,15 @@ fn assert_non_crate_hash_different(x: &Options, y: &Options) {
// When the user supplies --test we should implicitly supply --cfg test
#[test]
fn test_switch_implies_cfg_test() {
rustc_span::create_default_session_globals_then(|| {
let matches = optgroups().parse(&["--test".to_string()]).unwrap();
let (sess, cfg) = mk_session(matches);
let cfg = build_configuration(&sess, cfg);
sess_and_cfg(&["--test"], |_sess, cfg| {
assert!(cfg.contains(&(sym::test, None)));
});
})
}
// When the user supplies --test and --cfg test, don't implicitly add another --cfg test
#[test]
fn test_switch_implies_cfg_test_unless_cfg_test() {
rustc_span::create_default_session_globals_then(|| {
let matches = optgroups().parse(&["--test".to_string(), "--cfg=test".to_string()]).unwrap();
let (sess, cfg) = mk_session(matches);
let cfg = build_configuration(&sess, cfg);
sess_and_cfg(&["--test", "--cfg=test"], |_sess, cfg| {
let mut test_items = cfg.iter().filter(|&&(name, _)| name == sym::test);
assert!(test_items.next().is_some());
assert!(test_items.next().is_none());
@ -148,22 +153,15 @@ fn test_switch_implies_cfg_test_unless_cfg_test() {
#[test]
fn test_can_print_warnings() {
rustc_span::create_default_session_globals_then(|| {
let matches = optgroups().parse(&["-Awarnings".to_string()]).unwrap();
let (sess, _) = mk_session(matches);
sess_and_cfg(&["-Awarnings"], |sess, _cfg| {
assert!(!sess.dcx().can_emit_warnings());
});
rustc_span::create_default_session_globals_then(|| {
let matches =
optgroups().parse(&["-Awarnings".to_string(), "-Dwarnings".to_string()]).unwrap();
let (sess, _) = mk_session(matches);
sess_and_cfg(&["-Awarnings", "-Dwarnings"], |sess, _cfg| {
assert!(sess.dcx().can_emit_warnings());
});
rustc_span::create_default_session_globals_then(|| {
let matches = optgroups().parse(&["-Adead_code".to_string()]).unwrap();
let (sess, _) = mk_session(matches);
sess_and_cfg(&["-Adead_code"], |sess, _cfg| {
assert!(sess.dcx().can_emit_warnings());
});
}
@ -624,6 +622,7 @@ fn test_codegen_options_tracking_hash() {
tracked!(profile_generate, SwitchWithOptPath::Enabled(None));
tracked!(profile_use, Some(PathBuf::from("abc")));
tracked!(relocation_model, Some(RelocModel::Pic));
tracked!(relro_level, Some(RelroLevel::Full));
tracked!(soft_float, true);
tracked!(split_debuginfo, Some(SplitDebuginfo::Packed));
tracked!(symbol_mangling_version, Some(SymbolManglingVersion::V0));
@ -822,7 +821,6 @@ fn test_unstable_options_tracking_hash() {
tracked!(profile_sample_use, Some(PathBuf::from("abc")));
tracked!(profiler_runtime, "abc".to_string());
tracked!(relax_elf_relocations, Some(true));
tracked!(relro_level, Some(RelroLevel::Full));
tracked!(remap_cwd_prefix, Some(PathBuf::from("abc")));
tracked!(sanitizer, SanitizerSet::ADDRESS);
tracked!(sanitizer_cfi_canonical_jump_tables, None);

View File

@ -14,6 +14,7 @@ use rustc_session::lint::{self, BuiltinLintDiag, LintBuffer};
use rustc_session::{filesearch, Session};
use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::edition::Edition;
use rustc_span::source_map::SourceMapInputs;
use rustc_span::symbol::sym;
use rustc_target::spec::Target;
use session::output::{categorize_crate_type, CRATE_TYPES};
@ -65,8 +66,9 @@ fn init_stack_size() -> usize {
})
}
pub(crate) fn run_in_thread_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>(
fn run_in_thread_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>(
edition: Edition,
sm_inputs: SourceMapInputs,
f: F,
) -> R {
// The "thread pool" is a single spawned thread in the non-parallel
@ -84,7 +86,9 @@ pub(crate) fn run_in_thread_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: S
// name contains null bytes.
let r = builder
.spawn_scoped(s, move || {
rustc_span::create_session_globals_then(edition, || f(CurrentGcx::new()))
rustc_span::create_session_globals_then(edition, Some(sm_inputs), || {
f(CurrentGcx::new())
})
})
.unwrap()
.join();
@ -100,15 +104,17 @@ pub(crate) fn run_in_thread_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: S
pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>(
edition: Edition,
_threads: usize,
sm_inputs: SourceMapInputs,
f: F,
) -> R {
run_in_thread_with_globals(edition, f)
run_in_thread_with_globals(edition, sm_inputs, f)
}
#[cfg(parallel_compiler)]
pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>(
edition: Edition,
threads: usize,
sm_inputs: SourceMapInputs,
f: F,
) -> R {
use rustc_data_structures::{defer, jobserver, sync::FromDyn};
@ -120,7 +126,7 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send,
let registry = sync::Registry::new(std::num::NonZero::new(threads).unwrap());
if !sync::is_dyn_thread_safe() {
return run_in_thread_with_globals(edition, |current_gcx| {
return run_in_thread_with_globals(edition, sm_inputs, |current_gcx| {
// Register the thread for use with the `WorkerLocal` type.
registry.register();
@ -169,7 +175,7 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send,
// pool. Upon creation, each worker thread created gets a copy of the
// session globals in TLS. This is possible because `SessionGlobals` impls
// `Send` in the parallel compiler.
rustc_span::create_session_globals_then(edition, || {
rustc_span::create_session_globals_then(edition, Some(sm_inputs), || {
rustc_span::with_session_globals(|session_globals| {
let session_globals = FromDyn::from(session_globals);
builder

View File

@ -168,7 +168,7 @@ pub(super) fn unexpected_cfg_name(
diag.note("see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration");
} else {
diag.help(format!("to expect this configuration use `--check-cfg={inst}`"));
diag.note("see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration");
diag.note("see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration");
}
}
@ -272,6 +272,6 @@ pub(super) fn unexpected_cfg_value(
if !is_cfg_a_well_know_name {
diag.help(format!("to expect this configuration use `--check-cfg={inst}`"));
}
diag.note("see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration");
diag.note("see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration");
}
}

Some files were not shown because too many files have changed in this diff Show More