mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-26 05:44:26 +00:00
Merge from rustc
This commit is contained in:
commit
e8739886f2
@ -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",
|
||||
|
@ -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)`.
|
||||
|
@ -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();
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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,
|
||||
|
@ -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}`
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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 });
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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) => {
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)) => {
|
||||
|
@ -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(),
|
||||
|
@ -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(
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
|
@ -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() => {}
|
||||
|
@ -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,
|
||||
|
@ -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),
|
||||
}
|
||||
|
@ -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(())
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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)]
|
||||
|
@ -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)
|
||||
|
@ -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("=>"),
|
||||
|
@ -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.
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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(..)
|
||||
|
@ -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>,
|
||||
|
@ -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()], "");
|
||||
|
||||
|
@ -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}`
|
||||
|
||||
|
@ -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(¶m.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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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((
|
||||
|
@ -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.
|
||||
|
@ -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> {
|
||||
|
63
compiler/rustc_hir_analysis/src/errors/precise_captures.rs
Normal file
63
compiler/rustc_hir_analysis/src/errors/precise_captures.rs
Normal 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,
|
||||
}
|
@ -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();
|
||||
|
@ -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> {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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()?,
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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 }))
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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) =
|
||||
|
@ -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,
|
||||
}),
|
||||
],
|
||||
|
@ -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 }),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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(..), .. }))
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
};
|
||||
}
|
||||
|
@ -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()),
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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),
|
||||
|
@ -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()))
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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>)>>,
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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()))
|
||||
|
@ -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(),
|
||||
|
@ -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(
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
);
|
||||
|
@ -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(
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
))
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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(),
|
||||
|
@ -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)]
|
||||
|
@ -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
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user