mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-08 21:13:55 +00:00
hir: introduce QPath::LangItem
This commit introduces `QPath::LangItem` to the HIR and uses it in AST lowering instead of constructing a `hir::Path` from a slice of symbols. This might be better for performance, but is also much cleaner as the previous approach is fragile. In addition, it resolves a bug (#61019) where an extern crate imported as "std" would result in the paths created during AST lowering being resolved incorrectly (or not at all). Co-authored-by: Matthew Jasper <mjjasper1@gmail.com> Signed-off-by: David Wood <david@davidtw.co>
This commit is contained in:
parent
7dee5f824d
commit
762137e212
@ -449,7 +449,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
|
||||
// `::std::ops::Try::from_ok($tail_expr)`
|
||||
block.expr = Some(this.wrap_in_try_constructor(
|
||||
sym::from_ok,
|
||||
hir::LangItem::TryFromOk,
|
||||
try_span,
|
||||
tail_expr,
|
||||
ok_wrapped_span,
|
||||
@ -461,14 +461,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
|
||||
fn wrap_in_try_constructor(
|
||||
&mut self,
|
||||
method: Symbol,
|
||||
lang_item: hir::LangItem,
|
||||
method_span: Span,
|
||||
expr: &'hir hir::Expr<'hir>,
|
||||
overall_span: Span,
|
||||
) -> &'hir hir::Expr<'hir> {
|
||||
let path = &[sym::ops, sym::Try, method];
|
||||
let constructor =
|
||||
self.arena.alloc(self.expr_std_path(method_span, path, None, ThinVec::new()));
|
||||
self.arena.alloc(self.expr_lang_item_path(method_span, lang_item, ThinVec::new()));
|
||||
self.expr_call(overall_span, constructor, std::slice::from_ref(expr))
|
||||
}
|
||||
|
||||
@ -558,12 +557,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
// `future::from_generator`:
|
||||
let unstable_span =
|
||||
self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone());
|
||||
let gen_future = self.expr_std_path(
|
||||
unstable_span,
|
||||
&[sym::future, sym::from_generator],
|
||||
None,
|
||||
ThinVec::new(),
|
||||
);
|
||||
let gen_future =
|
||||
self.expr_lang_item_path(unstable_span, hir::LangItem::FromGenerator, ThinVec::new());
|
||||
|
||||
// `future::from_generator(generator)`:
|
||||
hir::ExprKind::Call(self.arena.alloc(gen_future), arena_vec![self; generator])
|
||||
@ -630,23 +625,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
// Use of `await` outside of an async context, we cannot use `task_context` here.
|
||||
self.expr_err(span)
|
||||
};
|
||||
let pin_ty_id = self.next_id();
|
||||
let new_unchecked_expr_kind = self.expr_call_std_assoc_fn(
|
||||
pin_ty_id,
|
||||
let new_unchecked = self.expr_call_lang_item_fn_mut(
|
||||
span,
|
||||
&[sym::pin, sym::Pin],
|
||||
"new_unchecked",
|
||||
hir::LangItem::PinNewUnchecked,
|
||||
arena_vec![self; ref_mut_pinned],
|
||||
);
|
||||
let new_unchecked = self.expr(span, new_unchecked_expr_kind, ThinVec::new());
|
||||
let get_context = self.expr_call_std_path_mut(
|
||||
let get_context = self.expr_call_lang_item_fn_mut(
|
||||
gen_future_span,
|
||||
&[sym::future, sym::get_context],
|
||||
hir::LangItem::GetContext,
|
||||
arena_vec![self; task_context],
|
||||
);
|
||||
let call = self.expr_call_std_path(
|
||||
let call = self.expr_call_lang_item_fn(
|
||||
span,
|
||||
&[sym::future, sym::Future, sym::poll],
|
||||
hir::LangItem::FuturePoll,
|
||||
arena_vec![self; new_unchecked, get_context],
|
||||
);
|
||||
self.arena.alloc(self.expr_unsafe(call))
|
||||
@ -659,11 +650,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
let x_ident = Ident::with_dummy_span(sym::result);
|
||||
let (x_pat, x_pat_hid) = self.pat_ident(span, x_ident);
|
||||
let x_expr = self.expr_ident(span, x_ident, x_pat_hid);
|
||||
let ready_pat = self.pat_std_enum(
|
||||
span,
|
||||
&[sym::task, sym::Poll, sym::Ready],
|
||||
arena_vec![self; x_pat],
|
||||
);
|
||||
let ready_field = self.single_pat_field(span, x_pat);
|
||||
let ready_pat = self.pat_lang_item_variant(span, hir::LangItem::PollReady, ready_field);
|
||||
let break_x = self.with_loop_scope(loop_node_id, move |this| {
|
||||
let expr_break =
|
||||
hir::ExprKind::Break(this.lower_loop_destination(None), Some(x_expr));
|
||||
@ -674,7 +662,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
|
||||
// `::std::task::Poll::Pending => {}`
|
||||
let pending_arm = {
|
||||
let pending_pat = self.pat_std_enum(span, &[sym::task, sym::Poll, sym::Pending], &[]);
|
||||
let pending_pat = self.pat_lang_item_variant(span, hir::LangItem::PollPending, &[]);
|
||||
let empty_block = self.expr_block_empty(span);
|
||||
self.arm(pending_pat, empty_block)
|
||||
};
|
||||
@ -842,16 +830,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
|
||||
/// Desugar `<start>..=<end>` into `std::ops::RangeInclusive::new(<start>, <end>)`.
|
||||
fn lower_expr_range_closed(&mut self, span: Span, e1: &Expr, e2: &Expr) -> hir::ExprKind<'hir> {
|
||||
let id = self.next_id();
|
||||
let e1 = self.lower_expr_mut(e1);
|
||||
let e2 = self.lower_expr_mut(e2);
|
||||
self.expr_call_std_assoc_fn(
|
||||
id,
|
||||
span,
|
||||
&[sym::ops, sym::RangeInclusive],
|
||||
"new",
|
||||
arena_vec![self; e1, e2],
|
||||
)
|
||||
let fn_path = hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, span);
|
||||
let fn_expr =
|
||||
self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path), ThinVec::new()));
|
||||
hir::ExprKind::Call(fn_expr, arena_vec![self; e1, e2])
|
||||
}
|
||||
|
||||
fn lower_expr_range(
|
||||
@ -863,12 +847,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
) -> hir::ExprKind<'hir> {
|
||||
use rustc_ast::ast::RangeLimits::*;
|
||||
|
||||
let path = match (e1, e2, lims) {
|
||||
(None, None, HalfOpen) => sym::RangeFull,
|
||||
(Some(..), None, HalfOpen) => sym::RangeFrom,
|
||||
(None, Some(..), HalfOpen) => sym::RangeTo,
|
||||
(Some(..), Some(..), HalfOpen) => sym::Range,
|
||||
(None, Some(..), Closed) => sym::RangeToInclusive,
|
||||
let lang_item = match (e1, e2, lims) {
|
||||
(None, None, HalfOpen) => hir::LangItem::RangeFull,
|
||||
(Some(..), None, HalfOpen) => hir::LangItem::RangeFrom,
|
||||
(None, Some(..), HalfOpen) => hir::LangItem::RangeTo,
|
||||
(Some(..), Some(..), HalfOpen) => hir::LangItem::Range,
|
||||
(None, Some(..), Closed) => hir::LangItem::RangeToInclusive,
|
||||
(Some(..), Some(..), Closed) => unreachable!(),
|
||||
(_, None, Closed) => {
|
||||
self.diagnostic().span_fatal(span, "inclusive range with no end").raise()
|
||||
@ -883,16 +867,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
}),
|
||||
);
|
||||
|
||||
let is_unit = fields.is_empty();
|
||||
let struct_path = [sym::ops, path];
|
||||
let struct_path = self.std_path(span, &struct_path, None, is_unit);
|
||||
let struct_path = hir::QPath::Resolved(None, struct_path);
|
||||
|
||||
if is_unit {
|
||||
hir::ExprKind::Path(struct_path)
|
||||
} else {
|
||||
hir::ExprKind::Struct(self.arena.alloc(struct_path), fields, None)
|
||||
}
|
||||
hir::ExprKind::Struct(self.arena.alloc(hir::QPath::LangItem(lang_item, span)), fields, None)
|
||||
}
|
||||
|
||||
fn lower_loop_destination(&mut self, destination: Option<(NodeId, Label)>) -> hir::Destination {
|
||||
@ -1412,9 +1387,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
let match_expr = {
|
||||
let iter = self.expr_ident(desugared_span, iter, iter_pat_nid);
|
||||
let ref_mut_iter = self.expr_mut_addr_of(desugared_span, iter);
|
||||
let next_path = &[sym::iter, sym::Iterator, sym::next];
|
||||
let next_expr =
|
||||
self.expr_call_std_path(desugared_span, next_path, arena_vec![self; ref_mut_iter]);
|
||||
let next_expr = self.expr_call_lang_item_fn(
|
||||
desugared_span,
|
||||
hir::LangItem::IteratorNext,
|
||||
arena_vec![self; ref_mut_iter],
|
||||
);
|
||||
let arms = arena_vec![self; pat_arm, break_arm];
|
||||
|
||||
self.expr_match(desugared_span, next_expr, arms, hir::MatchSource::ForLoopDesugar)
|
||||
@ -1472,8 +1449,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
|
||||
// `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
|
||||
let into_iter_expr = {
|
||||
let into_iter_path = &[sym::iter, sym::IntoIterator, sym::into_iter];
|
||||
self.expr_call_std_path(into_iter_span, into_iter_path, arena_vec![self; head])
|
||||
self.expr_call_lang_item_fn(
|
||||
into_iter_span,
|
||||
hir::LangItem::IntoIterIntoIter,
|
||||
arena_vec![self; head],
|
||||
)
|
||||
};
|
||||
|
||||
let match_expr = self.arena.alloc(self.expr_match(
|
||||
@ -1521,8 +1501,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
// expand <expr>
|
||||
let sub_expr = self.lower_expr_mut(sub_expr);
|
||||
|
||||
let path = &[sym::ops, sym::Try, sym::into_result];
|
||||
self.expr_call_std_path(unstable_span, path, arena_vec![self; sub_expr])
|
||||
self.expr_call_lang_item_fn(
|
||||
unstable_span,
|
||||
hir::LangItem::TryIntoResult,
|
||||
arena_vec![self; sub_expr],
|
||||
)
|
||||
};
|
||||
|
||||
// `#[allow(unreachable_code)]`
|
||||
@ -1558,12 +1541,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
let err_ident = Ident::with_dummy_span(sym::err);
|
||||
let (err_local, err_local_nid) = self.pat_ident(try_span, err_ident);
|
||||
let from_expr = {
|
||||
let from_path = &[sym::convert, sym::From, sym::from];
|
||||
let err_expr = self.expr_ident_mut(try_span, err_ident, err_local_nid);
|
||||
self.expr_call_std_path(try_span, from_path, arena_vec![self; err_expr])
|
||||
self.expr_call_lang_item_fn(
|
||||
try_span,
|
||||
hir::LangItem::FromFrom,
|
||||
arena_vec![self; err_expr],
|
||||
)
|
||||
};
|
||||
let from_err_expr =
|
||||
self.wrap_in_try_constructor(sym::from_error, unstable_span, from_expr, try_span);
|
||||
let from_err_expr = self.wrap_in_try_constructor(
|
||||
hir::LangItem::TryFromError,
|
||||
unstable_span,
|
||||
from_expr,
|
||||
try_span,
|
||||
);
|
||||
let thin_attrs = ThinVec::from(attrs);
|
||||
let catch_scope = self.catch_scopes.last().copied();
|
||||
let ret_expr = if let Some(catch_node) = catch_scope {
|
||||
@ -1674,63 +1664,32 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
self.arena.alloc(self.expr_call_mut(span, e, args))
|
||||
}
|
||||
|
||||
// Note: associated functions must use `expr_call_std_path`.
|
||||
fn expr_call_std_path_mut(
|
||||
fn expr_call_lang_item_fn_mut(
|
||||
&mut self,
|
||||
span: Span,
|
||||
path_components: &[Symbol],
|
||||
lang_item: hir::LangItem,
|
||||
args: &'hir [hir::Expr<'hir>],
|
||||
) -> hir::Expr<'hir> {
|
||||
let path =
|
||||
self.arena.alloc(self.expr_std_path(span, path_components, None, ThinVec::new()));
|
||||
let path = self.arena.alloc(self.expr_lang_item_path(span, lang_item, ThinVec::new()));
|
||||
self.expr_call_mut(span, path, args)
|
||||
}
|
||||
|
||||
fn expr_call_std_path(
|
||||
fn expr_call_lang_item_fn(
|
||||
&mut self,
|
||||
span: Span,
|
||||
path_components: &[Symbol],
|
||||
lang_item: hir::LangItem,
|
||||
args: &'hir [hir::Expr<'hir>],
|
||||
) -> &'hir hir::Expr<'hir> {
|
||||
self.arena.alloc(self.expr_call_std_path_mut(span, path_components, args))
|
||||
self.arena.alloc(self.expr_call_lang_item_fn_mut(span, lang_item, args))
|
||||
}
|
||||
|
||||
// Create an expression calling an associated function of an std type.
|
||||
//
|
||||
// Associated functions cannot be resolved through the normal `std_path` function,
|
||||
// as they are resolved differently and so cannot use `expr_call_std_path`.
|
||||
//
|
||||
// This function accepts the path component (`ty_path_components`) separately from
|
||||
// the name of the associated function (`assoc_fn_name`) in order to facilitate
|
||||
// separate resolution of the type and creation of a path referring to its associated
|
||||
// function.
|
||||
fn expr_call_std_assoc_fn(
|
||||
&mut self,
|
||||
ty_path_id: hir::HirId,
|
||||
span: Span,
|
||||
ty_path_components: &[Symbol],
|
||||
assoc_fn_name: &str,
|
||||
args: &'hir [hir::Expr<'hir>],
|
||||
) -> hir::ExprKind<'hir> {
|
||||
let ty_path = self.std_path(span, ty_path_components, None, false);
|
||||
let ty =
|
||||
self.arena.alloc(self.ty_path(ty_path_id, span, hir::QPath::Resolved(None, ty_path)));
|
||||
let fn_seg = self.arena.alloc(hir::PathSegment::from_ident(Ident::from_str(assoc_fn_name)));
|
||||
let fn_path = hir::QPath::TypeRelative(ty, fn_seg);
|
||||
let fn_expr =
|
||||
self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path), ThinVec::new()));
|
||||
hir::ExprKind::Call(fn_expr, args)
|
||||
}
|
||||
|
||||
fn expr_std_path(
|
||||
fn expr_lang_item_path(
|
||||
&mut self,
|
||||
span: Span,
|
||||
components: &[Symbol],
|
||||
params: Option<&'hir hir::GenericArgs<'hir>>,
|
||||
lang_item: hir::LangItem,
|
||||
attrs: AttrVec,
|
||||
) -> hir::Expr<'hir> {
|
||||
let path = self.std_path(span, components, params, true);
|
||||
self.expr(span, hir::ExprKind::Path(hir::QPath::Resolved(None, path)), attrs)
|
||||
self.expr(span, hir::ExprKind::Path(hir::QPath::LangItem(lang_item, span)), attrs)
|
||||
}
|
||||
|
||||
pub(super) fn expr_ident(
|
||||
|
@ -85,8 +85,6 @@ const HIR_ID_COUNTER_LOCKED: u32 = 0xFFFFFFFF;
|
||||
rustc_hir::arena_types!(rustc_arena::declare_arena, [], 'tcx);
|
||||
|
||||
struct LoweringContext<'a, 'hir: 'a> {
|
||||
crate_root: Option<Symbol>,
|
||||
|
||||
/// Used to assign IDs to HIR nodes that do not directly correspond to AST nodes.
|
||||
sess: &'a Session,
|
||||
|
||||
@ -189,16 +187,6 @@ pub trait ResolverAstLowering {
|
||||
/// This should only return `None` during testing.
|
||||
fn definitions(&mut self) -> &mut Definitions;
|
||||
|
||||
/// Given suffix `["b", "c", "d"]`, creates an AST path for `[::crate_root]::b::c::d` and
|
||||
/// resolves it based on `is_value`.
|
||||
fn resolve_str_path(
|
||||
&mut self,
|
||||
span: Span,
|
||||
crate_root: Option<Symbol>,
|
||||
components: &[Symbol],
|
||||
ns: Namespace,
|
||||
) -> (ast::Path, Res<NodeId>);
|
||||
|
||||
fn lint_buffer(&mut self) -> &mut LintBuffer;
|
||||
|
||||
fn next_node_id(&mut self) -> NodeId;
|
||||
@ -305,7 +293,6 @@ pub fn lower_crate<'a, 'hir>(
|
||||
let _prof_timer = sess.prof.verbose_generic_activity("hir_lowering");
|
||||
|
||||
LoweringContext {
|
||||
crate_root: sess.parse_sess.injected_crate_name.get().copied(),
|
||||
sess,
|
||||
resolver,
|
||||
nt_to_tokenstream,
|
||||
@ -2064,23 +2051,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
};
|
||||
|
||||
// "<Output = T>"
|
||||
let future_params = self.arena.alloc(hir::GenericArgs {
|
||||
let future_args = self.arena.alloc(hir::GenericArgs {
|
||||
args: &[],
|
||||
bindings: arena_vec![self; self.output_ty_binding(span, output_ty)],
|
||||
parenthesized: false,
|
||||
});
|
||||
|
||||
// ::std::future::Future<future_params>
|
||||
let future_path =
|
||||
self.std_path(span, &[sym::future, sym::Future], Some(future_params), false);
|
||||
|
||||
hir::GenericBound::Trait(
|
||||
hir::PolyTraitRef {
|
||||
trait_ref: hir::TraitRef { path: future_path, hir_ref_id: self.next_id() },
|
||||
bound_generic_params: &[],
|
||||
span,
|
||||
},
|
||||
hir::TraitBoundModifier::None,
|
||||
hir::GenericBound::LangItemTrait(
|
||||
// ::std::future::Future<future_params>
|
||||
hir::LangItem::FutureTraitLangItem,
|
||||
span,
|
||||
self.next_id(),
|
||||
future_args,
|
||||
)
|
||||
}
|
||||
|
||||
@ -2480,35 +2462,47 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
}
|
||||
|
||||
fn pat_ok(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
|
||||
self.pat_std_enum(span, &[sym::result, sym::Result, sym::Ok], arena_vec![self; pat])
|
||||
let field = self.single_pat_field(span, pat);
|
||||
self.pat_lang_item_variant(span, hir::LangItem::ResultOk, field)
|
||||
}
|
||||
|
||||
fn pat_err(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
|
||||
self.pat_std_enum(span, &[sym::result, sym::Result, sym::Err], arena_vec![self; pat])
|
||||
let field = self.single_pat_field(span, pat);
|
||||
self.pat_lang_item_variant(span, hir::LangItem::ResultErr, field)
|
||||
}
|
||||
|
||||
fn pat_some(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
|
||||
self.pat_std_enum(span, &[sym::option, sym::Option, sym::Some], arena_vec![self; pat])
|
||||
let field = self.single_pat_field(span, pat);
|
||||
self.pat_lang_item_variant(span, hir::LangItem::OptionSome, field)
|
||||
}
|
||||
|
||||
fn pat_none(&mut self, span: Span) -> &'hir hir::Pat<'hir> {
|
||||
self.pat_std_enum(span, &[sym::option, sym::Option, sym::None], &[])
|
||||
self.pat_lang_item_variant(span, hir::LangItem::OptionNone, &[])
|
||||
}
|
||||
|
||||
fn pat_std_enum(
|
||||
fn single_pat_field(
|
||||
&mut self,
|
||||
span: Span,
|
||||
components: &[Symbol],
|
||||
subpats: &'hir [&'hir hir::Pat<'hir>],
|
||||
) -> &'hir hir::Pat<'hir> {
|
||||
let path = self.std_path(span, components, None, true);
|
||||
let qpath = hir::QPath::Resolved(None, path);
|
||||
let pt = if subpats.is_empty() {
|
||||
hir::PatKind::Path(qpath)
|
||||
} else {
|
||||
hir::PatKind::TupleStruct(qpath, subpats, None)
|
||||
pat: &'hir hir::Pat<'hir>,
|
||||
) -> &'hir [hir::FieldPat<'hir>] {
|
||||
let field = hir::FieldPat {
|
||||
hir_id: self.next_id(),
|
||||
ident: Ident::new(sym::integer(0), span),
|
||||
is_shorthand: false,
|
||||
pat,
|
||||
span,
|
||||
};
|
||||
self.pat(span, pt)
|
||||
arena_vec![self; field]
|
||||
}
|
||||
|
||||
fn pat_lang_item_variant(
|
||||
&mut self,
|
||||
span: Span,
|
||||
lang_item: hir::LangItem,
|
||||
fields: &'hir [hir::FieldPat<'hir>],
|
||||
) -> &'hir hir::Pat<'hir> {
|
||||
let qpath = hir::QPath::LangItem(lang_item, span);
|
||||
self.pat(span, hir::PatKind::Struct(qpath, fields, false))
|
||||
}
|
||||
|
||||
fn pat_ident(&mut self, span: Span, ident: Ident) -> (&'hir hir::Pat<'hir>, hir::HirId) {
|
||||
@ -2541,42 +2535,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
self.arena.alloc(hir::Pat { hir_id: self.next_id(), kind, span })
|
||||
}
|
||||
|
||||
/// Given a suffix `["b", "c", "d"]`, returns path `::std::b::c::d` when
|
||||
/// `fld.cx.use_std`, and `::core::b::c::d` otherwise.
|
||||
/// The path is also resolved according to `is_value`.
|
||||
fn std_path(
|
||||
&mut self,
|
||||
span: Span,
|
||||
components: &[Symbol],
|
||||
params: Option<&'hir hir::GenericArgs<'hir>>,
|
||||
is_value: bool,
|
||||
) -> &'hir hir::Path<'hir> {
|
||||
let ns = if is_value { Namespace::ValueNS } else { Namespace::TypeNS };
|
||||
let (path, res) = self.resolver.resolve_str_path(span, self.crate_root, components, ns);
|
||||
|
||||
let mut segments: Vec<_> = path
|
||||
.segments
|
||||
.iter()
|
||||
.map(|segment| {
|
||||
let res = self.expect_full_res(segment.id);
|
||||
hir::PathSegment {
|
||||
ident: segment.ident,
|
||||
hir_id: Some(self.lower_node_id(segment.id)),
|
||||
res: Some(self.lower_res(res)),
|
||||
infer_args: true,
|
||||
args: None,
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
segments.last_mut().unwrap().args = params;
|
||||
|
||||
self.arena.alloc(hir::Path {
|
||||
span,
|
||||
res: res.map_id(|_| panic!("unexpected `NodeId`")),
|
||||
segments: self.arena.alloc_from_iter(segments),
|
||||
})
|
||||
}
|
||||
|
||||
fn ty_path(
|
||||
&mut self,
|
||||
mut hir_id: hir::HirId,
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::def::{DefKind, Namespace, Res};
|
||||
use crate::def_id::DefId;
|
||||
crate use crate::hir_id::HirId;
|
||||
use crate::itemlikevisit;
|
||||
use crate::{itemlikevisit, LangItem};
|
||||
|
||||
use rustc_ast::ast::{self, CrateSugar, LlvmAsmDialect};
|
||||
use rustc_ast::ast::{AttrVec, Attribute, FloatTy, IntTy, Label, LitKind, StrStyle, UintTy};
|
||||
@ -363,6 +363,8 @@ pub enum TraitBoundModifier {
|
||||
#[derive(Debug, HashStable_Generic)]
|
||||
pub enum GenericBound<'hir> {
|
||||
Trait(PolyTraitRef<'hir>, TraitBoundModifier),
|
||||
// FIXME(davidtwco): Introduce `PolyTraitRef::LangItem`
|
||||
LangItemTrait(LangItem, Span, HirId, &'hir GenericArgs<'hir>),
|
||||
Outlives(Lifetime),
|
||||
}
|
||||
|
||||
@ -377,6 +379,7 @@ impl GenericBound<'_> {
|
||||
pub fn span(&self) -> Span {
|
||||
match self {
|
||||
&GenericBound::Trait(ref t, ..) => t.span,
|
||||
&GenericBound::LangItemTrait(_, span, ..) => span,
|
||||
&GenericBound::Outlives(ref l) => l.span,
|
||||
}
|
||||
}
|
||||
@ -1419,10 +1422,10 @@ impl Expr<'_> {
|
||||
self.is_place_expr(|_| true)
|
||||
}
|
||||
|
||||
// Whether this is a place expression.
|
||||
// `allow_projections_from` should return `true` if indexing a field or
|
||||
// index expression based on the given expression should be considered a
|
||||
// place expression.
|
||||
/// Whether this is a place expression.
|
||||
///
|
||||
/// `allow_projections_from` should return `true` if indexing a field or index expression based
|
||||
/// on the given expression should be considered a place expression.
|
||||
pub fn is_place_expr(&self, mut allow_projections_from: impl FnMut(&Self) -> bool) -> bool {
|
||||
match self.kind {
|
||||
ExprKind::Path(QPath::Resolved(_, ref path)) => match path.res {
|
||||
@ -1441,6 +1444,9 @@ impl Expr<'_> {
|
||||
allow_projections_from(base) || base.is_place_expr(allow_projections_from)
|
||||
}
|
||||
|
||||
// Lang item paths cannot currently be local variables or statics.
|
||||
ExprKind::Path(QPath::LangItem(..)) => false,
|
||||
|
||||
// Partially qualified paths in expressions can only legally
|
||||
// refer to associated items which are always rvalues.
|
||||
ExprKind::Path(QPath::TypeRelative(..))
|
||||
@ -1677,6 +1683,40 @@ pub enum QPath<'hir> {
|
||||
/// `<Vec>::new`, and `T::X::Y::method` into `<<<T>::X>::Y>::method`,
|
||||
/// the `X` and `Y` nodes each being a `TyKind::Path(QPath::TypeRelative(..))`.
|
||||
TypeRelative(&'hir Ty<'hir>, &'hir PathSegment<'hir>),
|
||||
|
||||
/// Reference to a `#[lang = "foo"]` item.
|
||||
LangItem(LangItem, Span),
|
||||
}
|
||||
|
||||
impl<'hir> QPath<'hir> {
|
||||
/// Returns the span of this `QPath`.
|
||||
pub fn span(&self) -> Span {
|
||||
match *self {
|
||||
QPath::Resolved(_, path) => path.span,
|
||||
QPath::TypeRelative(_, ps) => ps.ident.span,
|
||||
QPath::LangItem(_, span) => span,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the span of the qself of this `QPath`. For example, `()` in
|
||||
/// `<() as Trait>::method`.
|
||||
pub fn qself_span(&self) -> Span {
|
||||
match *self {
|
||||
QPath::Resolved(_, path) => path.span,
|
||||
QPath::TypeRelative(qself, _) => qself.span,
|
||||
QPath::LangItem(_, span) => span,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the span of the last segment of this `QPath`. For example, `method` in
|
||||
/// `<() as Trait>::method`.
|
||||
pub fn last_segment_span(&self) -> Span {
|
||||
match *self {
|
||||
QPath::Resolved(_, path) => path.segments.last().unwrap().ident.span,
|
||||
QPath::TypeRelative(_, segment) => segment.ident.span,
|
||||
QPath::LangItem(_, span) => span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Hints at the original code for a let statement.
|
||||
|
@ -724,6 +724,7 @@ pub fn walk_qpath<'v, V: Visitor<'v>>(
|
||||
visitor.visit_ty(qself);
|
||||
visitor.visit_path_segment(span, segment);
|
||||
}
|
||||
QPath::LangItem(..) => {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -838,6 +839,10 @@ pub fn walk_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v GenericB
|
||||
GenericBound::Trait(ref typ, modifier) => {
|
||||
visitor.visit_poly_trait_ref(typ, modifier);
|
||||
}
|
||||
GenericBound::LangItemTrait(_, span, hir_id, args) => {
|
||||
visitor.visit_id(hir_id);
|
||||
visitor.visit_generic_args(span, args);
|
||||
}
|
||||
GenericBound::Outlives(ref lifetime) => visitor.visit_lifetime(lifetime),
|
||||
}
|
||||
}
|
||||
|
@ -1729,6 +1729,11 @@ impl<'a> State<'a> {
|
||||
colons_before_params,
|
||||
)
|
||||
}
|
||||
hir::QPath::LangItem(lang_item, span) => {
|
||||
self.s.word("#[lang = \"");
|
||||
self.print_ident(Ident::new(lang_item.name(), span));
|
||||
self.s.word("\"]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2142,6 +2147,11 @@ impl<'a> State<'a> {
|
||||
}
|
||||
self.print_poly_trait_ref(tref);
|
||||
}
|
||||
GenericBound::LangItemTrait(lang_item, span, ..) => {
|
||||
self.s.word("#[lang = \"");
|
||||
self.print_ident(Ident::new(lang_item.name(), *span));
|
||||
self.s.word("\"]");
|
||||
}
|
||||
GenericBound::Outlives(lt) => {
|
||||
self.print_lifetime(lt);
|
||||
}
|
||||
|
@ -1057,7 +1057,7 @@ impl TypeAliasBounds {
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
hir::QPath::Resolved(..) => false,
|
||||
hir::QPath::Resolved(..) | hir::QPath::LangItem(..) => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -703,7 +703,7 @@ impl<'tcx> LateContext<'tcx> {
|
||||
pub fn qpath_res(&self, qpath: &hir::QPath<'_>, id: hir::HirId) -> Res {
|
||||
match *qpath {
|
||||
hir::QPath::Resolved(_, ref path) => path.res,
|
||||
hir::QPath::TypeRelative(..) => self
|
||||
hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self
|
||||
.maybe_typeck_results()
|
||||
.and_then(|typeck_results| typeck_results.type_dependent_def(id))
|
||||
.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)),
|
||||
|
@ -445,7 +445,7 @@ impl<'tcx> TypeckResults<'tcx> {
|
||||
pub fn qpath_res(&self, qpath: &hir::QPath<'_>, id: hir::HirId) -> Res {
|
||||
match *qpath {
|
||||
hir::QPath::Resolved(_, ref path) => path.res,
|
||||
hir::QPath::TypeRelative(..) => self
|
||||
hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self
|
||||
.type_dependent_def(id)
|
||||
.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)),
|
||||
}
|
||||
|
@ -526,7 +526,8 @@ fn visit_expr<'tcx>(ir: &mut IrMaps<'tcx>, expr: &'tcx Expr<'tcx>) {
|
||||
| hir::ExprKind::Yield(..)
|
||||
| hir::ExprKind::Type(..)
|
||||
| hir::ExprKind::Err
|
||||
| hir::ExprKind::Path(hir::QPath::TypeRelative(..)) => {
|
||||
| hir::ExprKind::Path(hir::QPath::TypeRelative(..))
|
||||
| hir::ExprKind::Path(hir::QPath::LangItem(..)) => {
|
||||
intravisit::walk_expr(ir, expr);
|
||||
}
|
||||
}
|
||||
@ -1310,7 +1311,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||
|
||||
hir::ExprKind::Lit(..)
|
||||
| hir::ExprKind::Err
|
||||
| hir::ExprKind::Path(hir::QPath::TypeRelative(..)) => succ,
|
||||
| hir::ExprKind::Path(hir::QPath::TypeRelative(..))
|
||||
| hir::ExprKind::Path(hir::QPath::LangItem(..)) => succ,
|
||||
|
||||
// Note that labels have been resolved, so we don't need to look
|
||||
// at the label ident
|
||||
|
@ -1325,7 +1325,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
|
||||
Res::Def(kind, def_id) => Some((kind, def_id)),
|
||||
_ => None,
|
||||
},
|
||||
hir::QPath::TypeRelative(..) => self
|
||||
hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self
|
||||
.maybe_typeck_results
|
||||
.and_then(|typeck_results| typeck_results.type_dependent_def(id)),
|
||||
};
|
||||
@ -1340,7 +1340,9 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
|
||||
let sess = self.tcx.sess;
|
||||
let sm = sess.source_map();
|
||||
let name = match qpath {
|
||||
hir::QPath::Resolved(_, path) => sm.span_to_snippet(path.span).ok(),
|
||||
hir::QPath::Resolved(..) | hir::QPath::LangItem(..) => {
|
||||
sm.span_to_snippet(qpath.span()).ok()
|
||||
}
|
||||
hir::QPath::TypeRelative(_, segment) => Some(segment.ident.to_string()),
|
||||
};
|
||||
let kind = kind.descr(def_id);
|
||||
|
@ -1076,37 +1076,6 @@ impl ResolverAstLowering for Resolver<'_> {
|
||||
self.cstore().item_generics_num_lifetimes(def_id, sess)
|
||||
}
|
||||
|
||||
fn resolve_str_path(
|
||||
&mut self,
|
||||
span: Span,
|
||||
crate_root: Option<Symbol>,
|
||||
components: &[Symbol],
|
||||
ns: Namespace,
|
||||
) -> (ast::Path, Res) {
|
||||
let root = if crate_root.is_some() { kw::PathRoot } else { kw::Crate };
|
||||
let segments = iter::once(Ident::with_dummy_span(root))
|
||||
.chain(
|
||||
crate_root
|
||||
.into_iter()
|
||||
.chain(components.iter().cloned())
|
||||
.map(Ident::with_dummy_span),
|
||||
)
|
||||
.map(|i| self.new_ast_path_segment(i))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let path = ast::Path { span, segments };
|
||||
|
||||
let parent_scope = &ParentScope::module(self.graph_root);
|
||||
let res = match self.resolve_ast_path(&path, ns, parent_scope) {
|
||||
Ok(res) => res,
|
||||
Err((span, error)) => {
|
||||
self.report_error(span, error);
|
||||
Res::Err
|
||||
}
|
||||
};
|
||||
(path, res)
|
||||
}
|
||||
|
||||
fn get_partial_res(&mut self, id: NodeId) -> Option<PartialRes> {
|
||||
self.partial_res_map.get(&id).cloned()
|
||||
}
|
||||
|
@ -705,6 +705,7 @@ impl<'tcx> DumpVisitor<'tcx> {
|
||||
let trait_ref = match *super_bound {
|
||||
hir::GenericBound::Trait(ref trait_ref, _) => trait_ref,
|
||||
hir::GenericBound::Outlives(..) => continue,
|
||||
hir::GenericBound::LangItemTrait(..) => unimplemented!(),
|
||||
};
|
||||
|
||||
let trait_ref = &trait_ref.trait_ref;
|
||||
@ -765,6 +766,7 @@ impl<'tcx> DumpVisitor<'tcx> {
|
||||
let span = match path {
|
||||
hir::QPath::Resolved(_, path) => path.span,
|
||||
hir::QPath::TypeRelative(_, segment) => segment.ident.span,
|
||||
hir::QPath::LangItem(..) => unimplemented!(),
|
||||
};
|
||||
if self.span.filter_generated(span) {
|
||||
return;
|
||||
@ -783,6 +785,7 @@ impl<'tcx> DumpVisitor<'tcx> {
|
||||
self.visit_ty(ty);
|
||||
std::slice::from_ref(*segment)
|
||||
}
|
||||
hir::QPath::LangItem(..) => unimplemented!(),
|
||||
};
|
||||
for seg in segments {
|
||||
if let Some(ref generic_args) = seg.args {
|
||||
@ -1358,6 +1361,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> {
|
||||
let sub_span = match path {
|
||||
hir::QPath::Resolved(_, path) => path.segments.last().unwrap().ident.span,
|
||||
hir::QPath::TypeRelative(_, segment) => segment.ident.span,
|
||||
hir::QPath::LangItem(..) => unimplemented!(),
|
||||
};
|
||||
let span = self.span_from_span(sub_span);
|
||||
self.dumper.dump_ref(Ref {
|
||||
|
@ -555,6 +555,7 @@ impl<'tcx> SaveContext<'tcx> {
|
||||
let segment = match qpath {
|
||||
hir::QPath::Resolved(_, path) => path.segments.last().unwrap(),
|
||||
hir::QPath::TypeRelative(_, segment) => segment,
|
||||
hir::QPath::LangItem(..) => unimplemented!(),
|
||||
};
|
||||
match ty.kind {
|
||||
ty::Adt(def, _) => {
|
||||
@ -639,6 +640,7 @@ impl<'tcx> SaveContext<'tcx> {
|
||||
hir::QPath::TypeRelative(..) => self
|
||||
.maybe_typeck_results
|
||||
.map_or(Res::Err, |typeck_results| typeck_results.qpath_res(qpath, hir_id)),
|
||||
hir::QPath::LangItem(..) => unimplemented!(),
|
||||
},
|
||||
|
||||
Node::Binding(&hir::Pat {
|
||||
@ -653,6 +655,7 @@ impl<'tcx> SaveContext<'tcx> {
|
||||
let segment = match path {
|
||||
hir::QPath::Resolved(_, path) => path.segments.last(),
|
||||
hir::QPath::TypeRelative(_, segment) => Some(*segment),
|
||||
hir::QPath::LangItem(..) => unimplemented!(),
|
||||
};
|
||||
segment.and_then(|seg| {
|
||||
self.get_path_segment_data(seg).or_else(|| self.get_path_segment_data_with_id(seg, id))
|
||||
|
@ -286,6 +286,7 @@ impl<'hir> Sig for hir::Ty<'hir> {
|
||||
refs: vec![SigElement { id, start, end }],
|
||||
})
|
||||
}
|
||||
hir::TyKind::Path(hir::QPath::LangItem(..)) => unimplemented!(),
|
||||
hir::TyKind::TraitObject(bounds, ..) => {
|
||||
// FIXME recurse into bounds
|
||||
let bounds: Vec<hir::GenericBound<'_>> = bounds
|
||||
|
@ -1202,6 +1202,36 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn instantiate_lang_item_trait_ref(
|
||||
&self,
|
||||
lang_item: hir::LangItem,
|
||||
span: Span,
|
||||
hir_id: hir::HirId,
|
||||
args: &GenericArgs<'_>,
|
||||
self_ty: Ty<'tcx>,
|
||||
bounds: &mut Bounds<'tcx>,
|
||||
) {
|
||||
let trait_def_id = self.tcx().require_lang_item(lang_item, Some(span));
|
||||
|
||||
let (substs, assoc_bindings, _) =
|
||||
self.create_substs_for_ast_path(span, trait_def_id, &[], args, false, Some(self_ty));
|
||||
let poly_trait_ref = ty::Binder::bind(ty::TraitRef::new(trait_def_id, substs));
|
||||
bounds.trait_bounds.push((poly_trait_ref, span, Constness::NotConst));
|
||||
|
||||
let mut dup_bindings = FxHashMap::default();
|
||||
for binding in assoc_bindings {
|
||||
let _: Result<_, ErrorReported> = self.add_predicates_for_ast_type_binding(
|
||||
hir_id,
|
||||
poly_trait_ref,
|
||||
&binding,
|
||||
bounds,
|
||||
false,
|
||||
&mut dup_bindings,
|
||||
span,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn ast_path_to_mono_trait_ref(
|
||||
&self,
|
||||
span: Span,
|
||||
@ -1392,6 +1422,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
trait_bounds.push((b, Constness::NotConst))
|
||||
}
|
||||
hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) => {}
|
||||
hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => self
|
||||
.instantiate_lang_item_trait_ref(
|
||||
lang_item, span, hir_id, args, param_ty, bounds,
|
||||
),
|
||||
hir::GenericBound::Outlives(ref l) => region_bounds.push(l),
|
||||
}
|
||||
}
|
||||
@ -2960,6 +2994,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
.map(|(ty, _, _)| ty)
|
||||
.unwrap_or_else(|_| tcx.ty_error())
|
||||
}
|
||||
hir::TyKind::Path(hir::QPath::LangItem(lang_item, span)) => {
|
||||
let def_id = tcx.require_lang_item(lang_item, Some(span));
|
||||
let (substs, _, _) = self.create_substs_for_ast_path(
|
||||
span,
|
||||
def_id,
|
||||
&[],
|
||||
&GenericArgs::none(),
|
||||
true,
|
||||
None,
|
||||
);
|
||||
self.normalize_ty(span, tcx.at(span).type_of(def_id).subst(tcx, substs))
|
||||
}
|
||||
hir::TyKind::Array(ref ty, ref length) => {
|
||||
let length_def_id = tcx.hir().local_def_id(length.hir_id);
|
||||
let length = ty::Const::from_anon_const(tcx, length_def_id);
|
||||
|
@ -236,6 +236,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
ExprKind::AddrOf(kind, mutbl, ref oprnd) => {
|
||||
self.check_expr_addr_of(kind, mutbl, oprnd, expected, expr)
|
||||
}
|
||||
ExprKind::Path(QPath::LangItem(lang_item, _)) => {
|
||||
self.check_lang_item_path(lang_item, expr)
|
||||
}
|
||||
ExprKind::Path(ref qpath) => self.check_expr_path(qpath, expr),
|
||||
ExprKind::InlineAsm(asm) => self.check_expr_asm(asm),
|
||||
ExprKind::LlvmInlineAsm(ref asm) => {
|
||||
@ -447,6 +450,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_lang_item_path(
|
||||
&self,
|
||||
lang_item: hir::LangItem,
|
||||
expr: &'tcx hir::Expr<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
self.resolve_lang_item_path(lang_item, expr.span, expr.hir_id).1
|
||||
}
|
||||
|
||||
fn check_expr_path(&self, qpath: &hir::QPath<'_>, expr: &'tcx hir::Expr<'tcx>) -> Ty<'tcx> {
|
||||
let tcx = self.tcx;
|
||||
let (res, opt_ty, segs) = self.resolve_ty_and_res_ufcs(qpath, expr.hir_id, expr.span);
|
||||
@ -1077,11 +1088,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
return self.tcx.ty_error();
|
||||
};
|
||||
|
||||
let path_span = match *qpath {
|
||||
QPath::Resolved(_, ref path) => path.span,
|
||||
QPath::TypeRelative(ref qself, _) => qself.span,
|
||||
};
|
||||
|
||||
// Prohibit struct expressions when non-exhaustive flag is set.
|
||||
let adt = adt_ty.ty_adt_def().expect("`check_struct_path` returned non-ADT type");
|
||||
if !adt.did.is_local() && variant.is_field_list_non_exhaustive() {
|
||||
@ -1099,7 +1105,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
adt_ty,
|
||||
expected,
|
||||
expr.hir_id,
|
||||
path_span,
|
||||
qpath.span(),
|
||||
variant,
|
||||
fields,
|
||||
base_expr.is_none(),
|
||||
|
@ -122,10 +122,9 @@ use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::ty::subst::{self, InternalSubsts, Subst, SubstsRef};
|
||||
use rustc_middle::ty::subst::{GenericArgKind, UserSelfTy, UserSubsts};
|
||||
use rustc_middle::ty::util::{Discr, IntTypeExt, Representability};
|
||||
use rustc_middle::ty::{
|
||||
self, AdtKind, CanonicalUserType, Const, GenericParamDefKind, RegionKind, ToPolyTraitRef,
|
||||
ToPredicate, Ty, TyCtxt, UserType, WithConstness,
|
||||
};
|
||||
use rustc_middle::ty::WithConstness;
|
||||
use rustc_middle::ty::{self, AdtKind, CanonicalUserType, Const, DefIdTree, GenericParamDefKind};
|
||||
use rustc_middle::ty::{RegionKind, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, UserType};
|
||||
use rustc_session::config::{self, EntryFnType};
|
||||
use rustc_session::lint;
|
||||
use rustc_session::parse::feature_err;
|
||||
@ -4430,10 +4429,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
qpath: &QPath<'_>,
|
||||
hir_id: hir::HirId,
|
||||
) -> Option<(&'tcx ty::VariantDef, Ty<'tcx>)> {
|
||||
let path_span = match *qpath {
|
||||
QPath::Resolved(_, ref path) => path.span,
|
||||
QPath::TypeRelative(ref qself, _) => qself.span,
|
||||
};
|
||||
let path_span = qpath.qself_span();
|
||||
let (def, ty) = self.finish_resolving_struct_path(qpath, path_span, hir_id);
|
||||
let variant = match def {
|
||||
Res::Err => {
|
||||
@ -4511,9 +4507,34 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
(result.map(|(kind, def_id)| Res::Def(kind, def_id)).unwrap_or(Res::Err), ty)
|
||||
}
|
||||
QPath::LangItem(lang_item, span) => {
|
||||
self.resolve_lang_item_path(lang_item, span, hir_id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_lang_item_path(
|
||||
&self,
|
||||
lang_item: hir::LangItem,
|
||||
span: Span,
|
||||
hir_id: hir::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);
|
||||
|
||||
let item_ty = if let DefKind::Variant = def_kind {
|
||||
self.tcx.type_of(self.tcx.parent(def_id).expect("variant w/out parent"))
|
||||
} else {
|
||||
self.tcx.type_of(def_id)
|
||||
};
|
||||
let substs = self.infcx.fresh_substs_for_item(span, def_id);
|
||||
let ty = item_ty.subst(self.tcx, substs);
|
||||
|
||||
self.write_resolution(hir_id, Ok((def_kind, def_id)));
|
||||
self.add_required_obligations(span, def_id, &substs);
|
||||
(Res::Def(def_kind, def_id), ty)
|
||||
}
|
||||
|
||||
/// Resolves an associated value path into a base type and associated constant, or method
|
||||
/// resolution. The newly resolved definition is written into `type_dependent_defs`.
|
||||
pub fn resolve_ty_and_res_ufcs<'b>(
|
||||
@ -4532,6 +4553,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
);
|
||||
}
|
||||
QPath::TypeRelative(ref qself, ref segment) => (self.to_ty(qself), qself, segment),
|
||||
QPath::LangItem(..) => bug!("`resolve_ty_and_res_ufcs` called on `LangItem`"),
|
||||
};
|
||||
if let Some(&cached_result) = self.typeck_results.borrow().type_dependent_defs().get(hir_id)
|
||||
{
|
||||
|
@ -947,13 +947,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// |
|
||||
// L | let A(()) = A(());
|
||||
// | ^ ^
|
||||
[] => {
|
||||
let qpath_span = match qpath {
|
||||
hir::QPath::Resolved(_, path) => path.span,
|
||||
hir::QPath::TypeRelative(_, ps) => ps.ident.span,
|
||||
};
|
||||
(qpath_span.shrink_to_hi(), pat_span)
|
||||
}
|
||||
[] => (qpath.span().shrink_to_hi(), pat_span),
|
||||
// Easy case. Just take the "lo" of the first sub-pattern and the "hi" of the
|
||||
// last sub-pattern. In the case of `A(x)` the first and last may coincide.
|
||||
// This looks like:
|
||||
|
@ -1959,6 +1959,20 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat
|
||||
predicates.extend(bounds.predicates(tcx, ty));
|
||||
}
|
||||
|
||||
&hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => {
|
||||
let mut bounds = Bounds::default();
|
||||
AstConv::instantiate_lang_item_trait_ref(
|
||||
&icx,
|
||||
lang_item,
|
||||
span,
|
||||
hir_id,
|
||||
args,
|
||||
ty,
|
||||
&mut bounds,
|
||||
);
|
||||
predicates.extend(bounds.predicates(tcx, ty));
|
||||
}
|
||||
|
||||
&hir::GenericBound::Outlives(ref lifetime) => {
|
||||
let region = AstConv::ast_region_to_region(&icx, lifetime, None);
|
||||
predicates.push((
|
||||
@ -2108,6 +2122,18 @@ fn predicates_from_bound<'tcx>(
|
||||
let _ = astconv.instantiate_poly_trait_ref(tr, constness, param_ty, &mut bounds);
|
||||
bounds.predicates(astconv.tcx(), param_ty)
|
||||
}
|
||||
hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => {
|
||||
let mut bounds = Bounds::default();
|
||||
astconv.instantiate_lang_item_trait_ref(
|
||||
lang_item,
|
||||
span,
|
||||
hir_id,
|
||||
args,
|
||||
param_ty,
|
||||
&mut bounds,
|
||||
);
|
||||
bounds.predicates(astconv.tcx(), param_ty)
|
||||
}
|
||||
hir::GenericBound::Outlives(ref lifetime) => {
|
||||
let region = astconv.ast_region_to_region(lifetime, None);
|
||||
let pred = ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(param_ty, region))
|
||||
|
@ -1,27 +1,4 @@
|
||||
//~ ERROR failed to resolve: could not find `future` in `std` [E0433]
|
||||
//~^ ERROR failed to resolve: could not find `pin` in `std` [E0433]
|
||||
//~^^ ERROR failed to resolve: could not find `future` in `std` [E0433]
|
||||
//~^^^ ERROR failed to resolve: could not find `future` in `std` [E0433]
|
||||
//~^^^^ ERROR failed to resolve: could not find `task` in `std` [E0433]
|
||||
//~^^^^^ ERROR failed to resolve: could not find `task` in `std` [E0433]
|
||||
//~^^^^^^ ERROR failed to resolve: could not find `future` in `std` [E0433]
|
||||
//~^^^^^^^ ERROR failed to resolve: could not find `future` in `std` [E0433]
|
||||
//~^^^^^^^^ ERROR failed to resolve: could not find `ops` in `std` [E0433]
|
||||
//~^^^^^^^^^ ERROR failed to resolve: could not find `option` in `std` [E0433]
|
||||
//~^^^^^^^^^^ ERROR failed to resolve: could not find `option` in `std` [E0433]
|
||||
//~^^^^^^^^^^^ ERROR failed to resolve: could not find `iter` in `std` [E0433]
|
||||
//~^^^^^^^^^^^^ ERROR failed to resolve: could not find `iter` in `std` [E0433]
|
||||
//~^^^^^^^^^^^^^ ERROR failed to resolve: could not find `ops` in `std` [E0433]
|
||||
//~^^^^^^^^^^^^^^ ERROR failed to resolve: could not find `option` in `std` [E0433]
|
||||
//~^^^^^^^^^^^^^^^ ERROR failed to resolve: could not find `option` in `std` [E0433]
|
||||
//~^^^^^^^^^^^^^^^^ ERROR failed to resolve: could not find `iter` in `std` [E0433]
|
||||
//~^^^^^^^^^^^^^^^^^ ERROR failed to resolve: could not find `iter` in `std` [E0433]
|
||||
//~^^^^^^^^^^^^^^^^^^ ERROR failed to resolve: could not find `ops` in `std` [E0433]
|
||||
//~^^^^^^^^^^^^^^^^^^^ ERROR failed to resolve: could not find `result` in `std` [E0433]
|
||||
//~^^^^^^^^^^^^^^^^^^^^ ERROR failed to resolve: could not find `convert` in `std` [E0433]
|
||||
//~^^^^^^^^^^^^^^^^^^^^^ ERROR failed to resolve: could not find `ops` in `std` [E0433]
|
||||
//~^^^^^^^^^^^^^^^^^^^^^^ ERROR failed to resolve: could not find `result` in `std` [E0433]
|
||||
|
||||
// check-pass
|
||||
// edition:2018
|
||||
// aux-build:not-libstd.rs
|
||||
|
||||
|
@ -1,49 +0,0 @@
|
||||
error[E0433]: failed to resolve: could not find `future` in `std`
|
||||
|
||||
error[E0433]: failed to resolve: could not find `pin` in `std`
|
||||
|
||||
error[E0433]: failed to resolve: could not find `future` in `std`
|
||||
|
||||
error[E0433]: failed to resolve: could not find `future` in `std`
|
||||
|
||||
error[E0433]: failed to resolve: could not find `task` in `std`
|
||||
|
||||
error[E0433]: failed to resolve: could not find `task` in `std`
|
||||
|
||||
error[E0433]: failed to resolve: could not find `future` in `std`
|
||||
|
||||
error[E0433]: failed to resolve: could not find `future` in `std`
|
||||
|
||||
error[E0433]: failed to resolve: could not find `ops` in `std`
|
||||
|
||||
error[E0433]: failed to resolve: could not find `option` in `std`
|
||||
|
||||
error[E0433]: failed to resolve: could not find `option` in `std`
|
||||
|
||||
error[E0433]: failed to resolve: could not find `iter` in `std`
|
||||
|
||||
error[E0433]: failed to resolve: could not find `iter` in `std`
|
||||
|
||||
error[E0433]: failed to resolve: could not find `ops` in `std`
|
||||
|
||||
error[E0433]: failed to resolve: could not find `option` in `std`
|
||||
|
||||
error[E0433]: failed to resolve: could not find `option` in `std`
|
||||
|
||||
error[E0433]: failed to resolve: could not find `iter` in `std`
|
||||
|
||||
error[E0433]: failed to resolve: could not find `iter` in `std`
|
||||
|
||||
error[E0433]: failed to resolve: could not find `ops` in `std`
|
||||
|
||||
error[E0433]: failed to resolve: could not find `result` in `std`
|
||||
|
||||
error[E0433]: failed to resolve: could not find `convert` in `std`
|
||||
|
||||
error[E0433]: failed to resolve: could not find `ops` in `std`
|
||||
|
||||
error[E0433]: failed to resolve: could not find `result` in `std`
|
||||
|
||||
error: aborting due to 23 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0433`.
|
Loading…
Reference in New Issue
Block a user