diff --git a/src/librustc_ast_lowering/expr.rs b/src/librustc_ast_lowering/expr.rs index f9e54903a661a..65c9cd2e203d1 100644 --- a/src/librustc_ast_lowering/expr.rs +++ b/src/librustc_ast_lowering/expr.rs @@ -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 `..=` into `std::ops::RangeInclusive::new(, )`. 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() { ... }` 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 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)) - } - - // 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) + self.arena.alloc(self.expr_call_lang_item_fn_mut(span, lang_item, 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( diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs index 7cfde3fc6d2dc..a2962008a6bd4 100644 --- a/src/librustc_ast_lowering/lib.rs +++ b/src/librustc_ast_lowering/lib.rs @@ -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, - /// 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, - components: &[Symbol], - ns: Namespace, - ) -> (ast::Path, Res); - 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> { }; // "" - 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 - 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 + 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, diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs index 928235adac30c..e1ec60bcc0a2c 100644 --- a/src/librustc_hir/hir.rs +++ b/src/librustc_hir/hir.rs @@ -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> { /// `::new`, and `T::X::Y::method` into `<<::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. diff --git a/src/librustc_hir/intravisit.rs b/src/librustc_hir/intravisit.rs index 23d642731da4d..66ef017713447 100644 --- a/src/librustc_hir/intravisit.rs +++ b/src/librustc_hir/intravisit.rs @@ -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), } } diff --git a/src/librustc_hir_pretty/lib.rs b/src/librustc_hir_pretty/lib.rs index 2298a80ae4f1f..e124db9e355dd 100644 --- a/src/librustc_hir_pretty/lib.rs +++ b/src/librustc_hir_pretty/lib.rs @@ -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); } diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 3859d0f163ad5..97830e6c86f39 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1057,7 +1057,7 @@ impl TypeAliasBounds { _ => false, } } - hir::QPath::Resolved(..) => false, + hir::QPath::Resolved(..) | hir::QPath::LangItem(..) => false, } } diff --git a/src/librustc_lint/context.rs b/src/librustc_lint/context.rs index 31d30a264a59e..5b91b77e4f02d 100644 --- a/src/librustc_lint/context.rs +++ b/src/librustc_lint/context.rs @@ -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)), diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs index 6887f72932267..3b10cb5388506 100644 --- a/src/librustc_middle/ty/context.rs +++ b/src/librustc_middle/ty/context.rs @@ -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)), } diff --git a/src/librustc_passes/liveness.rs b/src/librustc_passes/liveness.rs index 6477f8da008ad..62c8680a85798 100644 --- a/src/librustc_passes/liveness.rs +++ b/src/librustc_passes/liveness.rs @@ -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 diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index a3f2668691fd8..deb4277cb3854 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -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); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 339a5ae6675e7..32b8ea410ad22 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -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, - 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::>(); - - 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 { self.partial_res_map.get(&id).cloned() } diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index f33d2f46aa269..c1c165a9901f8 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -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 { diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index ca98ada4e5729..a7eb344ff09f7 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -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)) diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index 33355c4c558fb..6a9ad3c38f496 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -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> = bounds diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 5170a060c5fe0..5e52a5ef16fb5 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -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); diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index e88f13a1f3ab6..e2c90cce178fe 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -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(), diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index a625b5ea40567..c46d2388f3d93 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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) { diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index 1c78bef98527a..35c7b7a703cc0 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -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: diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index da1f3ea62f239..15743b0643662 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -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)) diff --git a/src/test/ui/hygiene/hir-res-hygiene.rs b/src/test/ui/hygiene/hir-res-hygiene.rs index e5af1000dd53e..c26cf5fdb5b05 100644 --- a/src/test/ui/hygiene/hir-res-hygiene.rs +++ b/src/test/ui/hygiene/hir-res-hygiene.rs @@ -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 diff --git a/src/test/ui/hygiene/hir-res-hygiene.stderr b/src/test/ui/hygiene/hir-res-hygiene.stderr deleted file mode 100644 index 73a1bd5c62632..0000000000000 --- a/src/test/ui/hygiene/hir-res-hygiene.stderr +++ /dev/null @@ -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`.