]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #54671 - petrochenkov:extpre2015, r=nikomatsakis
authorbors <bors@rust-lang.org>
Wed, 17 Oct 2018 01:59:28 +0000 (01:59 +0000)
committerbors <bors@rust-lang.org>
Wed, 17 Oct 2018 01:59:28 +0000 (01:59 +0000)
resolve: Scale back hard-coded extern prelude additions on 2015 edition

https://github.com/rust-lang/rust/pull/54404 stabilized `feature(extern_prelude)` on 2015 edition, including the hard-coded parts not passed with `--extern`.
First of all, I'd want to confirm that this is intended stabilization, rather than a part of the "extended beta" scheme that's going to be reverted before releasing stable.
(EDIT: to clarify - this is a question, I'm \*asking\* for confirmation, rather than give it.)

Second, on 2015 edition extern prelude is not so fundamentally tied to imports and is a mere convenience, so this PR scales them back to the uncontroversial subset.
The "uncontroversial subset" means that if libcore is injected it brings `core` into prelude, if libstd is injected it brings `std` and `core` into prelude.
On 2015 edition this can be implemented through the library prelude (rather than hard-coding in the compiler) right now, I'll do it in a follow-up PR.

UPDATE: The change is done for both 2015 and 2018 editions now as discussed below.

Closes https://github.com/rust-lang/rust/issues/53166

1  2 
src/librustc/session/mod.rs
src/librustc/ty/context.rs
src/librustc/ty/item_path.rs
src/librustc/ty/mod.rs
src/librustc_driver/driver.rs

index e983ddc3108d7e62a862c4d8edded6c9afd77b7a,8e06191f3dd7feee920c7bd4a449ba0623793361..1ca60d54f7a3d0c935d15c444bb6ffd5f2367806
@@@ -35,7 -35,6 +35,6 @@@ use syntax::edition::Edition
  use syntax::feature_gate::{self, AttributeType};
  use syntax::json::JsonEmitter;
  use syntax::source_map;
- use syntax::symbol::Symbol;
  use syntax::parse::{self, ParseSess};
  use syntax_pos::{MultiSpan, Span};
  use util::profiling::SelfProfiler;
@@@ -166,10 -165,6 +165,6 @@@ pub struct Session 
  
      /// Cap lint level specified by a driver specifically.
      pub driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
-     /// All the crate names specified with `--extern`, and the builtin ones.
-     /// Starting with the Rust 2018 edition, absolute paths resolve in this set.
-     pub extern_prelude: FxHashSet<Symbol>,
  }
  
  pub struct PerfStats {
@@@ -703,8 -698,8 +698,8 @@@ impl Session 
          match self.opts.maybe_sysroot {
              Some(ref sysroot) => sysroot,
              None => self.default_sysroot
 -                .as_ref()
 -                .expect("missing sysroot and default_sysroot in Session"),
 +                        .as_ref()
 +                        .expect("missing sysroot and default_sysroot in Session"),
          }
      }
      pub fn target_filesearch(&self, kind: PathKind) -> filesearch::FileSearch<'_> {
      pub fn set_incr_session_load_dep_graph(&self, load: bool) {
          let mut incr_comp_session = self.incr_comp_session.borrow_mut();
  
 -        match *incr_comp_session {
 -            IncrCompSession::Active {
 -                ref mut load_dep_graph,
 -                ..
 -            } => {
 -                *load_dep_graph = load;
 -            }
 -            _ => {}
 +        if let IncrCompSession::Active { ref mut load_dep_graph, .. } = *incr_comp_session {
 +            *load_dep_graph = load;
          }
      }
  
      /// This expends fuel if applicable, and records fuel if applicable.
      pub fn consider_optimizing<T: Fn() -> String>(&self, crate_name: &str, msg: T) -> bool {
          let mut ret = true;
 -        match self.optimization_fuel_crate {
 -            Some(ref c) if c == crate_name => {
 -                assert!(self.query_threads() == 1);
 +        if let Some(ref c) = self.optimization_fuel_crate {
 +            if c == crate_name {
 +                assert_eq!(self.query_threads(), 1);
                  let fuel = self.optimization_fuel_limit.get();
                  ret = fuel != 0;
                  if fuel == 0 && !self.out_of_fuel.get() {
                      self.optimization_fuel_limit.set(fuel - 1);
                  }
              }
 -            _ => {}
          }
 -        match self.print_fuel_crate {
 -            Some(ref c) if c == crate_name => {
 -                assert!(self.query_threads() == 1);
 +        if let Some(ref c) = self.print_fuel_crate {
 +            if c == crate_name {
 +                assert_eq!(self.query_threads(), 1);
                  self.print_fuel.set(self.print_fuel.get() + 1);
              }
 -            _ => {}
          }
          ret
      }
@@@ -1100,11 -1103,14 +1095,11 @@@ pub fn build_session_
      source_map: Lrc<source_map::SourceMap>,
  ) -> Session {
      let host_triple = TargetTriple::from_triple(config::host_triple());
 -    let host = match Target::search(&host_triple) {
 -        Ok(t) => t,
 -        Err(e) => {
 -            span_diagnostic
 -                .fatal(&format!("Error loading host specification: {}", e))
 -                .raise();
 -        }
 -    };
 +    let host = Target::search(&host_triple).unwrap_or_else(|e|
 +        span_diagnostic
 +            .fatal(&format!("Error loading host specification: {}", e))
 +            .raise()
 +    );
      let target_cfg = config::build_target_config(&sopts, &span_diagnostic);
  
      let p_s = parse::ParseSess::with_span_handler(span_diagnostic, source_map);
      let print_fuel_crate = sopts.debugging_opts.print_fuel.clone();
      let print_fuel = LockCell::new(0);
  
 -    let working_dir = match env::current_dir() {
 -        Ok(dir) => dir,
 -        Err(e) => p_s.span_diagnostic
 +    let working_dir = env::current_dir().unwrap_or_else(|e|
 +        p_s.span_diagnostic
              .fatal(&format!("Current directory is invalid: {}", e))
 -            .raise(),
 -    };
 +            .raise()
 +    );
      let working_dir = file_path_mapping.map_prefix(working_dir);
  
      let cgu_reuse_tracker = if sopts.debugging_opts.query_dep_graph {
          CguReuseTracker::new_disabled()
      };
  
-     let mut extern_prelude: FxHashSet<Symbol> =
-         sopts.externs.iter().map(|kv| Symbol::intern(kv.0)).collect();
-     // HACK(eddyb) this ignores the `no_{core,std}` attributes.
-     // FIXME(eddyb) warn (somewhere) if core/std is used with `no_{core,std}`.
-     // if !attr::contains_name(&krate.attrs, "no_core") {
-     // if !attr::contains_name(&krate.attrs, "no_std") {
-     extern_prelude.insert(Symbol::intern("core"));
-     extern_prelude.insert(Symbol::intern("std"));
-     extern_prelude.insert(Symbol::intern("meta"));
      let sess = Session {
          target: target_cfg,
          host,
          has_global_allocator: Once::new(),
          has_panic_handler: Once::new(),
          driver_lint_caps: FxHashMap(),
-         extern_prelude,
      };
  
      validate_commandline_args_with_session_available(&sess);
index 6f0f258a2175495f217fa5e8ff03fd11bced073b,5e15ca16b97cdfb7884801f8c8d38d1583c02858..1bccd05af83237f82e1b1823d57bea542ca8d20e
@@@ -33,7 -33,7 +33,7 @@@ use middle::resolve_lifetime::{self, Ob
  use middle::stability;
  use mir::{self, Mir, interpret};
  use mir::interpret::Allocation;
 -use ty::subst::{CanonicalSubsts, Kind, Substs, Subst};
 +use ty::subst::{CanonicalUserSubsts, Kind, Substs, Subst};
  use ty::ReprOptions;
  use traits;
  use traits::{Clause, Clauses, GoalKind, Goal, Goals};
@@@ -383,7 -383,7 +383,7 @@@ pub struct TypeckTables<'tcx> 
      /// If the user wrote `foo.collect::<Vec<_>>()`, then the
      /// canonical substitutions would include only `for<X> { Vec<X>
      /// }`.
 -    user_substs: ItemLocalMap<CanonicalSubsts<'tcx>>,
 +    user_substs: ItemLocalMap<CanonicalUserSubsts<'tcx>>,
  
      adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
  
@@@ -573,14 -573,14 +573,14 @@@ impl<'tcx> TypeckTables<'tcx> 
          self.node_substs.get(&id.local_id).cloned()
      }
  
 -    pub fn user_substs_mut(&mut self) -> LocalTableInContextMut<'_, CanonicalSubsts<'tcx>> {
 +    pub fn user_substs_mut(&mut self) -> LocalTableInContextMut<'_, CanonicalUserSubsts<'tcx>> {
          LocalTableInContextMut {
              local_id_root: self.local_id_root,
              data: &mut self.user_substs
          }
      }
  
 -    pub fn user_substs(&self, id: hir::HirId) -> Option<CanonicalSubsts<'tcx>> {
 +    pub fn user_substs(&self, id: hir::HirId) -> Option<CanonicalUserSubsts<'tcx>> {
          validate_hir_id_for_typeck_tables(self.local_id_root, id, false);
          self.user_substs.get(&id.local_id).cloned()
      }
@@@ -936,8 -936,8 +936,8 @@@ pub struct GlobalCtxt<'tcx> 
      freevars: FxHashMap<DefId, Lrc<Vec<hir::Freevar>>>,
  
      maybe_unused_trait_imports: FxHashSet<DefId>,
      maybe_unused_extern_crates: Vec<(DefId, Span)>,
+     pub extern_prelude: FxHashSet<ast::Name>,
  
      // Internal cache for metadata decoding. No need to track deps on this.
      pub rcache: Lock<FxHashMap<ty::CReaderCacheKey, Ty<'tcx>>>,
@@@ -1223,6 -1223,7 +1223,7 @@@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, '
                      .into_iter()
                      .map(|(id, sp)| (hir.local_def_id(id), sp))
                      .collect(),
+             extern_prelude: resolutions.extern_prelude,
              hir,
              def_path_hash_to_def_id,
              queries: query::Queries::new(
index c4a25971da3ad15145514e407ad45874c7d80130,ca4cafd0a73912e3efdec339cd68fc6da2f43231..2e635c6ecdecb7475de13c383f96a1eac5f26332
@@@ -289,7 -289,7 +289,7 @@@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, '
                  // printing the `CrateRoot` so we don't prepend a `crate::` to paths.
                  let mut is_prelude_crate = false;
                  if let DefPathData::CrateRoot = self.def_key(parent_did).disambiguated_data.data {
-                     if self.sess.extern_prelude.contains(&data.as_interned_str().as_symbol()) {
+                     if self.extern_prelude.contains(&data.as_interned_str().as_symbol()) {
                          is_prelude_crate = true;
                      }
                  }
@@@ -436,7 -436,7 +436,7 @@@ pub fn characteristic_def_id_of_type(ty
      match ty.sty {
          ty::Adt(adt_def, _) => Some(adt_def.did),
  
 -        ty::Dynamic(data, ..) => data.principal().map(|p| p.def_id()),
 +        ty::Dynamic(data, ..) => Some(data.principal().def_id()),
  
          ty::Array(subty, _) |
          ty::Slice(subty) => characteristic_def_id_of_type(subty),
diff --combined src/librustc/ty/mod.rs
index 4135d499c58532256fd045d3e97519d45fe52aac,ee6d2dfb065f048c2c5ff3929a3f9cd2213c3eca..45a70be5842fcab3818ae82f235ab89e35e91a61
@@@ -36,7 -36,7 +36,7 @@@ use ty::subst::{Subst, Substs}
  use ty::util::{IntTypeExt, Discr};
  use ty::walk::TypeWalker;
  use util::captures::Captures;
- use util::nodemap::{NodeSet, DefIdMap, FxHashMap};
+ use util::nodemap::{NodeSet, DefIdMap, FxHashMap, FxHashSet};
  use arena::SyncDroplessArena;
  use session::DataTypeKind;
  
@@@ -57,7 -57,6 +57,7 @@@ use syntax::symbol::{keywords, Symbol, 
  use syntax_pos::{DUMMY_SP, Span};
  
  use smallvec;
 +use rustc_data_structures::indexed_vec::Idx;
  use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
                                             HashStable};
  
@@@ -141,6 -140,7 +141,7 @@@ pub struct Resolutions 
      pub maybe_unused_trait_imports: NodeSet,
      pub maybe_unused_extern_crates: Vec<(NodeId, Span)>,
      pub export_map: ExportMap,
+     pub extern_prelude: FxHashSet<Name>,
  }
  
  #[derive(Clone, Copy, PartialEq, Eq, Debug)]
@@@ -1457,10 -1457,10 +1458,10 @@@ impl<'tcx> InstantiatedPredicates<'tcx
  /// "Universes" are used during type- and trait-checking in the
  /// presence of `for<..>` binders to control what sets of names are
  /// visible. Universes are arranged into a tree: the root universe
 -/// contains names that are always visible. But when you enter into
 -/// some subuniverse, then it may add names that are only visible
 -/// within that subtree (but it can still name the names of its
 -/// ancestor universes).
 +/// contains names that are always visible. Each child then adds a new
 +/// set of names that are visible, in addition to those of its parent.
 +/// We say that the child universe "extends" the parent universe with
 +/// new names.
  ///
  /// To make this more concrete, consider this program:
  ///
  /// ```
  ///
  /// The struct name `Foo` is in the root universe U0. But the type
 -/// parameter `T`, introduced on `bar`, is in a subuniverse U1 --
 -/// i.e., within `bar`, we can name both `T` and `Foo`, but outside of
 -/// `bar`, we cannot name `T`. Then, within the type of `y`, the
 -/// region `'a` is in a subuniverse U2 of U1, because we can name it
 -/// inside the fn type but not outside.
 +/// parameter `T`, introduced on `bar`, is in an extended universe U1
 +/// -- i.e., within `bar`, we can name both `T` and `Foo`, but outside
 +/// of `bar`, we cannot name `T`. Then, within the type of `y`, the
 +/// region `'a` is in a universe U2 that extends U1, because we can
 +/// name it inside the fn type but not outside.
  ///
  /// Universes are used to do type- and trait-checking around these
  /// "forall" binders (also called **universal quantification**). The
  /// declared, but a type name in a non-zero universe is a placeholder
  /// type -- an idealized representative of "types in general" that we
  /// use for checking generic functions.
 -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
 -pub struct UniverseIndex(u32);
 -
 -impl UniverseIndex {
 -    /// The root universe, where things that the user defined are
 -    /// visible.
 -    pub const ROOT: Self = UniverseIndex(0);
 +newtype_index! {
 +    pub struct UniverseIndex {
 +        DEBUG_FORMAT = "U{}",
 +    }
 +}
  
 -    /// The "max universe" -- this isn't really a valid universe, but
 -    /// it's useful sometimes as a "starting value" when you are
 -    /// taking the minimum of a (non-empty!) set of universes.
 -    pub const MAX: Self = UniverseIndex(::std::u32::MAX);
 +impl_stable_hash_for!(struct UniverseIndex { private });
  
 -    /// Creates a universe index from the given integer.  Not to be
 -    /// used lightly lest you pick a bad value. But sometimes we
 -    /// convert universe indices into integers and back for various
 -    /// reasons.
 -    pub fn from_u32(index: u32) -> Self {
 -        UniverseIndex(index)
 -    }
 +impl UniverseIndex {
 +    pub const ROOT: UniverseIndex = UniverseIndex::from_u32_const(0);
  
 -    /// A "subuniverse" corresponds to being inside a `forall` quantifier.
 -    /// So, for example, suppose we have this type in universe `U`:
 +    /// Returns the "next" universe index in order -- this new index
 +    /// is considered to extend all previous universes. This
 +    /// corresponds to entering a `forall` quantifier.  So, for
 +    /// example, suppose we have this type in universe `U`:
      ///
      /// ```
      /// for<'a> fn(&'a u32)
      /// ```
      ///
      /// Once we "enter" into this `for<'a>` quantifier, we are in a
 -    /// subuniverse of `U` -- in this new universe, we can name the
 -    /// region `'a`, but that region was not nameable from `U` because
 -    /// it was not in scope there.
 -    pub fn subuniverse(self) -> UniverseIndex {
 -        UniverseIndex(self.0.checked_add(1).unwrap())
 -    }
 -
 -    /// True if the names in this universe are a subset of the names in `other`.
 -    pub fn is_subset_of(self, other: UniverseIndex) -> bool {
 -        self.0 <= other.0
 -    }
 -
 -    pub fn as_u32(&self) -> u32 {
 -        self.0
 -    }
 -
 -    pub fn as_usize(&self) -> usize {
 -        self.0 as usize
 -    }
 -}
 -
 -impl fmt::Debug for UniverseIndex {
 -    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
 -        write!(fmt, "U{}", self.as_u32())
 -    }
 -}
 -
 -impl From<u32> for UniverseIndex {
 -    fn from(index: u32) -> Self {
 -        UniverseIndex(index)
 +    /// new universe that extends `U` -- in this new universe, we can
 +    /// name the region `'a`, but that region was not nameable from
 +    /// `U` because it was not in scope there.
 +    pub fn next_universe(self) -> UniverseIndex {
 +        UniverseIndex::from_u32(self.private.checked_add(1).unwrap())
 +    }
 +
 +    /// True if `self` can name a name from `other` -- in other words,
 +    /// if the set of names in `self` is a superset of those in
 +    /// `other`.
 +    pub fn can_name(self, other: UniverseIndex) -> bool {
 +        self.private >= other.private
      }
  }
  
index 223df7cbb1874cb48fe2feaf0d3d19ac15aa80b1,3b0acfd6f8c12c60e622f77050fe7cc32525210e..4f48b00c93707a7aa05dfbc7a8fd8e8fa860403b
@@@ -44,7 -44,7 +44,7 @@@ use serialize::json
  
  use std::any::Any;
  use std::env;
 -use std::ffi::{OsStr, OsString};
 +use std::ffi::OsString;
  use std::fs;
  use std::io::{self, Write};
  use std::iter;
@@@ -790,6 -790,7 +790,7 @@@ wher
                  trait_map: resolver.trait_map,
                  maybe_unused_trait_imports: resolver.maybe_unused_trait_imports,
                  maybe_unused_extern_crates: resolver.maybe_unused_extern_crates,
+                 extern_prelude: resolver.extern_prelude,
              },
  
              analysis: ty::CrateAnalysis {
@@@ -1021,7 -1022,6 +1022,7 @@@ wher
              .cloned()
              .collect();
          missing_fragment_specifiers.sort();
 +
          for span in missing_fragment_specifiers {
              let lint = lint::builtin::MISSING_FRAGMENT_SPECIFIER;
              let msg = "missing fragment specifier";
@@@ -1473,7 -1473,7 +1474,7 @@@ fn write_out_deps(sess: &Session, outpu
              .collect();
          let mut file = fs::File::create(&deps_filename)?;
          for path in out_filenames {
 -            write!(file, "{}: {}\n\n", path.display(), files.join(" "))?;
 +            writeln!(file, "{}: {}\n", path.display(), files.join(" "))?;
          }
  
          // Emit a fake target for each input file to the compilation. This
          Ok(())
      })();
  
 -    match result {
 -        Ok(()) => {}
 -        Err(e) => {
 -            sess.fatal(&format!(
 -                "error writing dependencies to `{}`: {}",
 -                deps_filename.display(),
 -                e
 -            ));
 -        }
 +    if let Err(e) = result {
 +        sess.fatal(&format!(
 +            "error writing dependencies to `{}`: {}",
 +            deps_filename.display(),
 +            e
 +        ));
      }
  }
  
@@@ -1518,7 -1521,6 +1519,7 @@@ pub fn collect_crate_types(session: &Se
                              Symbol::intern("proc-macro"),
                              Symbol::intern("bin")
                          ];
 +
                          if let ast::MetaItemKind::NameValue(spanned) = a.meta().unwrap().node {
                              let span = spanned.span;
                              let lev_candidate = find_best_match_for_name(
                          }
                          None
                      }
 -                    _ => {
 +                    None => {
                          session
                              .struct_span_err(a.span, "`crate_type` requires a value")
                              .note("for example: `#![crate_type=\"lib\"]`")
              base.push(::rustc_codegen_utils::link::default_output_for_target(
                  session,
              ));
 +        } else {
 +            base.sort();
 +            base.dedup();
          }
 -        base.sort();
 -        base.dedup();
      }
  
 -    base.into_iter()
 -        .filter(|crate_type| {
 -            let res = !::rustc_codegen_utils::link::invalid_output_for_target(session, *crate_type);
 +    base.retain(|crate_type| {
 +        let res = !::rustc_codegen_utils::link::invalid_output_for_target(session, *crate_type);
  
 -            if !res {
 -                session.warn(&format!(
 -                    "dropping unsupported crate type `{}` for target `{}`",
 -                    *crate_type, session.opts.target_triple
 -                ));
 -            }
 +        if !res {
 +            session.warn(&format!(
 +                "dropping unsupported crate type `{}` for target `{}`",
 +                *crate_type, session.opts.target_triple
 +            ));
 +        }
  
 -            res
 -        })
 -        .collect()
 +        res
 +    });
 +
 +    base
  }
  
  pub fn compute_crate_disambiguator(session: &Session) -> CrateDisambiguator {
@@@ -1650,14 -1651,17 +1651,14 @@@ pub fn build_output_filenames
              // "-" as input file will cause the parser to read from stdin so we
              // have to make up a name
              // We want to toss everything after the final '.'
 -            let dirpath = match *odir {
 -                Some(ref d) => d.clone(),
 -                None => PathBuf::new(),
 -            };
 +            let dirpath = (*odir).as_ref().cloned().unwrap_or_default();
  
              // If a crate name is present, we use it as the link name
              let stem = sess.opts
                  .crate_name
                  .clone()
                  .or_else(|| attr::find_crate_name(attrs).map(|n| n.to_string()))
 -                .unwrap_or(input.filestem());
 +                .unwrap_or_else(|| input.filestem().to_owned());
  
              OutputFilenames {
                  out_directory: dirpath,
                  sess.warn("ignoring -C extra-filename flag due to -o flag");
              }
  
 -            let cur_dir = Path::new("");
 -
              OutputFilenames {
 -                out_directory: out_file.parent().unwrap_or(cur_dir).to_path_buf(),
 +                out_directory: out_file.parent().unwrap_or_else(|| Path::new("")).to_path_buf(),
                  out_filestem: out_file
                      .file_stem()
 -                    .unwrap_or(OsStr::new(""))
 +                    .unwrap_or_default()
                      .to_str()
                      .unwrap()
                      .to_string(),