diff --git a/src/etc/platform-intrinsics/x86/avx.json b/src/etc/platform-intrinsics/x86/avx.json index 2c1492c2954c8..08524fbd6dd8a 100644 --- a/src/etc/platform-intrinsics/x86/avx.json +++ b/src/etc/platform-intrinsics/x86/avx.json @@ -8,6 +8,69 @@ "ret": "f(32-64)", "args": ["0", "0"] }, + { + "intrinsic": "256_broadcast_{0.data_type}", + "width": [256], + "llvm": "vbroadcastf128.{0.data_type}.256", + "ret": "f(32-64)", + "args": ["s8SPc"] + }, + { + "intrinsic": "256_cvtepi32_pd", + "width": [256], + "llvm": "cvtdq2.pd.256", + "ret": "f64", + "args": ["s32h"] + }, + { + "intrinsic": "256_cvtepi32_ps", + "width": [256], + "llvm": "cvtdq2.ps.256", + "ret": "f32", + "args": ["s32"] + }, + { + "intrinsic": "256_cvtpd_epi32", + "width": [256], + "llvm": "cvt.pd2dq.256", + "ret": "s32h", + "args": ["f64"] + }, + { + "intrinsic": "256_cvtpd_ps", + "width": [256], + "llvm": "cvt.pd2.ps.256", + "ret": "f32h", + "args": ["f64"] + }, + { + "intrinsic": "256_cvtps_epi32", + "width": [256], + "llvm": "cvt.ps2dq.256", + "ret": "s32", + "args": ["f32"] + }, + { + "intrinsic": "256_cvtps_pd", + "width": [256], + "llvm": "cvt.ps2.pd.256", + "ret": "f64", + "args": ["f32h"] + }, + { + "intrinsic": "256_cvttpd_epi32", + "width": [256], + "llvm": "cvtt.pd2dq.256", + "ret": "s32h", + "args": ["f64"] + }, + { + "intrinsic": "256_cvttps_epi32", + "width": [256], + "llvm": "cvtt.ps2dq.256", + "ret": "s32", + "args": ["f32"] + }, { "intrinsic": "256_dp_ps", "width": [256], diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs index 3eca4624bc17d..e671dd73431e6 100644 --- a/src/librustc/middle/infer/mod.rs +++ b/src/librustc/middle/infer/mod.rs @@ -1120,11 +1120,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { .map(|method| resolve_ty(method.ty))) } + pub fn errors_since_creation(&self) -> bool { + self.tcx.sess.err_count() - self.err_count_on_creation != 0 + } + pub fn node_type(&self, id: ast::NodeId) -> Ty<'tcx> { match self.tables.borrow().node_types.get(&id) { Some(&t) => t, // FIXME - None if self.tcx.sess.err_count() - self.err_count_on_creation != 0 => + None if self.errors_since_creation() => self.tcx.types.err, None => { self.tcx.sess.bug( @@ -1147,7 +1151,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { free_regions: &FreeRegionMap, subject_node_id: ast::NodeId) { let errors = self.region_vars.resolve_regions(free_regions, subject_node_id); - self.report_region_errors(&errors); // see error_reporting.rs + if !self.errors_since_creation() { + // As a heuristic, just skip reporting region errors + // altogether if other errors have been reported while + // this infcx was in use. This is totally hokey but + // otherwise we have a hard time separating legit region + // errors from silly ones. + self.report_region_errors(&errors); // see error_reporting.rs + } } pub fn ty_to_string(&self, t: Ty<'tcx>) -> String { diff --git a/src/librustc_platform_intrinsics/x86.rs b/src/librustc_platform_intrinsics/x86.rs index 168ae79ab748f..d8aaf151267f6 100644 --- a/src/librustc_platform_intrinsics/x86.rs +++ b/src/librustc_platform_intrinsics/x86.rs @@ -498,6 +498,56 @@ pub fn find<'tcx>(_tcx: &TyCtxt<'tcx>, name: &str) -> Option { output: v(f(64), 4), definition: Named("llvm.x86.avx.addsub.pd.256") }, + "256_broadcast_ps" => Intrinsic { + inputs: vec![p(true, i(8), None)], + output: v(f(32), 8), + definition: Named("llvm.x86.avx.vbroadcastf128.ps.256") + }, + "256_broadcast_pd" => Intrinsic { + inputs: vec![p(true, i(8), None)], + output: v(f(64), 4), + definition: Named("llvm.x86.avx.vbroadcastf128.pd.256") + }, + "256_cvtepi32_pd" => Intrinsic { + inputs: vec![v(i(32), 4)], + output: v(f(64), 4), + definition: Named("llvm.x86.avx.cvtdq2.pd.256") + }, + "256_cvtepi32_ps" => Intrinsic { + inputs: vec![v(i(32), 8)], + output: v(f(32), 8), + definition: Named("llvm.x86.avx.cvtdq2.ps.256") + }, + "256_cvtpd_epi32" => Intrinsic { + inputs: vec![v(f(64), 4)], + output: v(i(32), 4), + definition: Named("llvm.x86.avx.cvt.pd2dq.256") + }, + "256_cvtpd_ps" => Intrinsic { + inputs: vec![v(f(64), 4)], + output: v(f(32), 4), + definition: Named("llvm.x86.avx.cvt.pd2.ps.256") + }, + "256_cvtps_epi32" => Intrinsic { + inputs: vec![v(f(32), 8)], + output: v(i(32), 8), + definition: Named("llvm.x86.avx.cvt.ps2dq.256") + }, + "256_cvtps_pd" => Intrinsic { + inputs: vec![v(f(32), 4)], + output: v(f(64), 4), + definition: Named("llvm.x86.avx.cvt.ps2.pd.256") + }, + "256_cvttpd_epi32" => Intrinsic { + inputs: vec![v(f(64), 4)], + output: v(i(32), 4), + definition: Named("llvm.x86.avx.cvtt.pd2dq.256") + }, + "256_cvttps_epi32" => Intrinsic { + inputs: vec![v(f(32), 8)], + output: v(i(32), 8), + definition: Named("llvm.x86.avx.cvtt.ps2dq.256") + }, "256_dp_ps" => Intrinsic { inputs: vec![v(f(32), 8), v(f(32), 8), i_(32, 8)], output: v(f(32), 8), diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 970f54207baf5..9a4173bad6e4c 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1166,8 +1166,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { unresolved_imports: 0, current_module: graph_root, - value_ribs: Vec::new(), - type_ribs: Vec::new(), + value_ribs: vec![Rib::new(ModuleRibKind(graph_root))], + type_ribs: vec![Rib::new(ModuleRibKind(graph_root))], label_ribs: Vec::new(), current_trait_ref: None, @@ -1354,7 +1354,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// On success, returns the resolved module, and the closest *private* /// module found to the destination when resolving this path. fn resolve_module_path(&mut self, - module_: Module<'a>, module_path: &[Name], use_lexical_scope: UseLexicalScopeFlag, span: Span) @@ -1365,10 +1364,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { debug!("(resolving module path for import) processing `{}` rooted at `{}`", names_to_string(module_path), - module_to_string(&module_)); + module_to_string(self.current_module)); // Resolve the module prefix, if any. - let module_prefix_result = self.resolve_module_prefix(module_, module_path); + let module_prefix_result = self.resolve_module_prefix(module_path); let search_module; let start_index; @@ -1410,8 +1409,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // This is not a crate-relative path. We resolve the // first component of the path in the current lexical // scope and then proceed to resolve below that. - match self.resolve_item_in_lexical_scope(module_, - module_path[0], + match self.resolve_item_in_lexical_scope(module_path[0], TypeNS, true) { Failed(err) => return Failed(err), @@ -1442,64 +1440,40 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { span) } + /// This function resolves `name` in `namespace` in the current lexical scope, returning + /// Success(binding) if `name` resolves to an item, or Failed(None) if `name` does not resolve + /// or resolves to a type parameter or local variable. + /// n.b. `resolve_identifier_in_local_ribs` also resolves names in the current lexical scope. + /// /// Invariant: This must only be called during main resolution, not during /// import resolution. fn resolve_item_in_lexical_scope(&mut self, - module_: Module<'a>, name: Name, namespace: Namespace, record_used: bool) -> ResolveResult<&'a NameBinding<'a>> { - debug!("(resolving item in lexical scope) resolving `{}` in namespace {:?} in `{}`", - name, - namespace, - module_to_string(&module_)); - - // Proceed up the scope chain looking for parent modules. - let mut search_module = module_; - loop { - // Resolve the name in the parent module. - match self.resolve_name_in_module(search_module, name, namespace, true, record_used) { - Failed(Some((span, msg))) => { - resolve_error(self, span, ResolutionError::FailedToResolve(&msg)); - } - Failed(None) => (), // Continue up the search chain. - Indeterminate => { - // We couldn't see through the higher scope because of an - // unresolved import higher up. Bail. - - debug!("(resolving item in lexical scope) indeterminate higher scope; bailing"); - return Indeterminate; - } - Success(binding) => { - // We found the module. - debug!("(resolving item in lexical scope) found name in module, done"); - return Success(binding); - } + // Walk backwards up the ribs in scope. + for i in (0 .. self.get_ribs(namespace).len()).rev() { + if let Some(_) = self.get_ribs(namespace)[i].bindings.get(&name).cloned() { + // The name resolves to a type parameter or local variable, so return Failed(None). + return Failed(None); } - // Go to the next parent. - match search_module.parent_link { - NoParentLink => { - // No more parents. This module was unresolved. - debug!("(resolving item in lexical scope) unresolved module: no parent module"); - return Failed(None); - } - ModuleParentLink(parent_module_node, _) => { - if search_module.is_normal() { - // We stop the search here. - debug!("(resolving item in lexical scope) unresolved module: not \ - searching through module parents"); - return Failed(None); - } else { - search_module = parent_module_node; - } - } - BlockParentLink(parent_module_node, _) => { - search_module = parent_module_node; + if let ModuleRibKind(module) = self.get_ribs(namespace)[i].kind { + if let Success(binding) = self.resolve_name_in_module(module, + name, + namespace, + true, + record_used) { + // The name resolves to an item. + return Success(binding); } + // We can only see through anonymous modules + if module.def.is_some() { return Failed(None); } } } + + Failed(None) } /// Returns the nearest normal module parent of the given module. @@ -1535,9 +1509,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// Resolves a "module prefix". A module prefix is one or both of (a) `self::`; /// (b) some chain of `super::`. /// grammar: (SELF MOD_SEP ) ? (SUPER MOD_SEP) * - fn resolve_module_prefix(&mut self, - module_: Module<'a>, - module_path: &[Name]) + fn resolve_module_prefix(&mut self, module_path: &[Name]) -> ResolveResult> { // Start at the current module if we see `self` or `super`, or at the // top of the crate otherwise. @@ -1546,6 +1518,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { "super" => 0, _ => return Success(NoPrefixFound), }; + let module_ = self.current_module; let mut containing_module = self.get_nearest_normal_module_parent_or_self(module_); // Now loop through all the `super`s we find. @@ -1905,7 +1878,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { trait_path: &Path, path_depth: usize) -> Result { - if let Some(path_res) = self.resolve_path(id, trait_path, path_depth, TypeNS, true) { + if let Some(path_res) = self.resolve_path(id, trait_path, path_depth, TypeNS) { if let Def::Trait(_) = path_res.base_def { debug!("(resolving trait) found trait def: {:?}", path_res); Ok(path_res) @@ -1963,7 +1936,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &hir::WherePredicate::BoundPredicate(_) | &hir::WherePredicate::RegionPredicate(_) => {} &hir::WherePredicate::EqPredicate(ref eq_pred) => { - let path_res = self.resolve_path(eq_pred.id, &eq_pred.path, 0, TypeNS, true); + let path_res = self.resolve_path(eq_pred.id, &eq_pred.path, 0, TypeNS); if let Some(PathResolution { base_def: Def::TyParam(..), .. }) = path_res { self.record_def(eq_pred.id, path_res.unwrap()); } else { @@ -2229,8 +2202,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let resolution = match self.resolve_possibly_assoc_item(ty.id, maybe_qself.as_ref(), path, - TypeNS, - true) { + TypeNS) { // `::a::b::c` is resolved by typeck alone. TypecheckRequired => { // Resolve embedded types. @@ -2255,7 +2227,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.record_def(ty.id, err_path_resolution()); // Keep reporting some errors even if they're ignored above. - self.resolve_path(ty.id, path, 0, TypeNS, true); + self.resolve_path(ty.id, path, 0, TypeNS); let kind = if maybe_qself.is_some() { "associated type" @@ -2433,8 +2405,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let resolution = match self.resolve_possibly_assoc_item(pat_id, None, path, - ValueNS, - false) { + ValueNS) { // The below shouldn't happen because all // qualified paths should be in PatKind::QPath. TypecheckRequired => @@ -2506,8 +2477,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let resolution = match self.resolve_possibly_assoc_item(pat_id, Some(qself), path, - ValueNS, - false) { + ValueNS) { TypecheckRequired => { // All `::CONST` should end up here, and will // require use of the trait map to resolve @@ -2557,7 +2527,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } PatKind::Struct(ref path, _, _) => { - match self.resolve_path(pat_id, path, 0, TypeNS, false) { + match self.resolve_path(pat_id, path, 0, TypeNS) { Some(definition) => { self.record_def(pattern.id, definition); } @@ -2591,8 +2561,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { name: Name, span: Span) -> BareIdentifierPatternResolution { - let module = self.current_module; - match self.resolve_item_in_lexical_scope(module, name, ValueNS, true) { + match self.resolve_item_in_lexical_scope(name, ValueNS, true) { Success(binding) => { debug!("(resolve bare identifier pattern) succeeded in finding {} at {:?}", name, @@ -2639,8 +2608,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { id: NodeId, maybe_qself: Option<&hir::QSelf>, path: &Path, - namespace: Namespace, - check_ribs: bool) + namespace: Namespace) -> AssocItemResolveResult { let max_assoc_types; @@ -2659,14 +2627,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } let mut resolution = self.with_no_errors(|this| { - this.resolve_path(id, path, 0, namespace, check_ribs) + this.resolve_path(id, path, 0, namespace) }); for depth in 1..max_assoc_types { if resolution.is_some() { break; } self.with_no_errors(|this| { - resolution = this.resolve_path(id, path, depth, TypeNS, true); + resolution = this.resolve_path(id, path, depth, TypeNS); }); } if let Some(Def::Mod(_)) = resolution.map(|r| r.base_def) { @@ -2676,16 +2644,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ResolveAttempt(resolution) } - /// If `check_ribs` is true, checks the local definitions first; i.e. - /// doesn't skip straight to the containing module. /// Skips `path_depth` trailing segments, which is also reflected in the /// returned value. See `middle::def::PathResolution` for more info. pub fn resolve_path(&mut self, id: NodeId, path: &Path, path_depth: usize, - namespace: Namespace, - check_ribs: bool) + namespace: Namespace) -> Option { let span = path.span; let segments = &path.segments[..path.segments.len() - path_depth]; @@ -2700,14 +2665,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Try to find a path to an item in a module. let last_ident = segments.last().unwrap().identifier; if segments.len() <= 1 { - let unqualified_def = self.resolve_identifier(last_ident, namespace, check_ribs, true); + let unqualified_def = self.resolve_identifier(last_ident, namespace, true); return unqualified_def.and_then(|def| self.adjust_local_def(def, span)) .map(|def| { PathResolution::new(def, path_depth) }); } - let unqualified_def = self.resolve_identifier(last_ident, namespace, check_ribs, false); + let unqualified_def = self.resolve_identifier(last_ident, namespace, false); let def = self.resolve_module_relative_path(span, segments, namespace); match (def, unqualified_def) { (Some(d), Some(ref ud)) if d == ud.def => { @@ -2727,7 +2692,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn resolve_identifier(&mut self, identifier: hir::Ident, namespace: Namespace, - check_ribs: bool, record_used: bool) -> Option { if identifier.name == special_idents::invalid.name { @@ -2743,24 +2707,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - if check_ribs { - match self.resolve_identifier_in_local_ribs(identifier, namespace, record_used) { - Some(def) => return Some(def), - None => {} - } - } - - // Check the items. - let module = self.current_module; - let name = identifier.unhygienic_name; - match self.resolve_item_in_lexical_scope(module, name, namespace, record_used) { - Success(binding) => binding.def().map(LocalDef::from_def), - Failed(Some((span, msg))) => { - resolve_error(self, span, ResolutionError::FailedToResolve(&msg)); - None - } - _ => None, - } + self.resolve_identifier_in_local_ribs(identifier, namespace, record_used) } // Resolve a local definition, potentially adjusting for closures. @@ -2866,8 +2813,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { .collect::>(); let containing_module; - let current_module = self.current_module; - match self.resolve_module_path(current_module, &module_path, UseLexicalScope, span) { + match self.resolve_module_path(&module_path, UseLexicalScope, span) { Failed(err) => { let (span, msg) = match err { Some((span, msg)) => (span, msg), @@ -3021,7 +2967,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { span: Span, name_path: &[ast::Name]) -> Option> { - let root = this.current_module; let last_name = name_path.last().unwrap(); if name_path.len() == 1 { @@ -3031,7 +2976,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { .and_then(NameBinding::module) } } else { - this.resolve_module_path(root, &name_path, UseLexicalScope, span).success() + this.resolve_module_path(&name_path, UseLexicalScope, span).success() } } @@ -3142,8 +3087,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let resolution = match self.resolve_possibly_assoc_item(expr.id, maybe_qself.as_ref(), path, - ValueNS, - true) { + ValueNS) { // `::a::b::c` is resolved by typeck alone. TypecheckRequired => { let method_name = path.segments.last().unwrap().identifier.name; @@ -3203,7 +3147,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // structs, which wouldn't result in this error.) let path_name = path_names_to_string(path, 0); let type_res = self.with_no_errors(|this| { - this.resolve_path(expr.id, path, 0, TypeNS, false) + this.resolve_path(expr.id, path, 0, TypeNS) }); self.record_def(expr.id, err_path_resolution()); @@ -3224,7 +3168,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } _ => { // Keep reporting some errors even if they're ignored above. - self.resolve_path(expr.id, path, 0, ValueNS, true); + self.resolve_path(expr.id, path, 0, ValueNS); let mut method_scope = false; self.value_ribs.iter().rev().all(|rib| { @@ -3271,10 +3215,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let name_path = path.segments.iter() .map(|seg| seg.identifier.name) .collect::>(); - let current_module = self.current_module; - match self.resolve_module_path(current_module, - &name_path[..], + match self.resolve_module_path(&name_path[..], UseLexicalScope, expr.span) { Success(_) => { @@ -3300,7 +3242,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Resolve the path to the structure it goes to. We don't // check to ensure that the path is actually a structure; that // is checked later during typeck. - match self.resolve_path(expr.id, path, 0, TypeNS, false) { + match self.resolve_path(expr.id, path, 0, TypeNS) { Some(definition) => self.record_def(expr.id, definition), None => { debug!("(resolving expression) didn't find struct def",); diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index ea16211c40d06..c4aa434092c0f 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -444,8 +444,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { module_to_string(&module_)); self.resolver - .resolve_module_path(module_, - &import_directive.module_path, + .resolve_module_path(&import_directive.module_path, UseLexicalScopeFlag::DontUseLexicalScope, import_directive.span) .and_then(|containing_module| { diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index bc6b4f83984b0..4c03abac9e867 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -26,6 +26,7 @@ use rustc::middle::stability; use rustc_front::hir; use core; +use clean::{Clean, Attributes}; use doctree::*; // looks to me like the first two of these are actually @@ -182,7 +183,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { please_inline: bool) -> Option { match path { hir::ViewPathSimple(dst, base) => { - if self.resolve_id(id, Some(dst), false, om, please_inline) { + if self.maybe_inline_local(id, Some(dst), false, om, please_inline) { None } else { Some(hir::ViewPathSimple(dst, base)) @@ -190,7 +191,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } hir::ViewPathList(p, paths) => { let mine = paths.into_iter().filter(|path| { - !self.resolve_id(path.node.id(), None, false, om, + !self.maybe_inline_local(path.node.id(), None, false, om, please_inline) }).collect::>(); @@ -201,9 +202,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } } - // these are feature gated anyway hir::ViewPathGlob(base) => { - if self.resolve_id(id, None, true, om, please_inline) { + if self.maybe_inline_local(id, None, true, om, please_inline) { None } else { Some(hir::ViewPathGlob(base)) @@ -213,8 +213,32 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } - fn resolve_id(&mut self, id: ast::NodeId, renamed: Option, + /// Tries to resolve the target of a `pub use` statement and inlines the + /// target if it is defined locally and would not be documented otherwise, + /// or when it is specifically requested with `please_inline`. + /// (the latter is the case when the import is marked `doc(inline)`) + /// + /// Cross-crate inlining occurs later on during crate cleaning + /// and follows different rules. + /// + /// Returns true if the target has been inlined. + fn maybe_inline_local(&mut self, id: ast::NodeId, renamed: Option, glob: bool, om: &mut Module, please_inline: bool) -> bool { + + fn inherits_doc_hidden(cx: &core::DocContext, mut node: ast::NodeId) -> bool { + while let Some(id) = cx.map.get_enclosing_scope(node) { + node = id; + let attrs = cx.map.attrs(node).clean(cx); + if attrs.list_def("doc").has_word("hidden") { + return true; + } + if node == ast::CRATE_NODE_ID { + break; + } + } + false + } + let tcx = match self.cx.tcx_opt() { Some(tcx) => tcx, None => return false @@ -226,9 +250,15 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { let analysis = match self.analysis { Some(analysis) => analysis, None => return false }; - if !please_inline && analysis.access_levels.is_public(def) { + + let is_private = !analysis.access_levels.is_public(def); + let is_hidden = inherits_doc_hidden(self.cx, def_node_id); + + // Only inline if requested or if the item would otherwise be stripped + if !please_inline && !is_private && !is_hidden { return false } + if !self.view_item_stack.insert(def_node_id) { return false } let ret = match tcx.map.get(def_node_id) { @@ -276,10 +306,10 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { let node = if item.vis == hir::Public { let please_inline = item.attrs.iter().any(|item| { match item.meta_item_list() { - Some(list) => { + Some(list) if &item.name()[..] == "doc" => { list.iter().any(|i| &i.name()[..] == "inline") } - None => false, + _ => false, } }); match self.visit_view_path(node, om, item.id, please_inline) { diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index a8bea2da83349..f7621b0131ad4 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -927,7 +927,7 @@ pub enum ExprKind { Binary(BinOp, P, P), /// A unary operation (For example: `!x`, `*x`) Unary(UnOp, P), - /// A literal (For example: `1u8`, `"foo"`) + /// A literal (For example: `1`, `"foo"`) Lit(P), /// A cast (`foo as f64`) Cast(P, P), @@ -1016,7 +1016,7 @@ pub enum ExprKind { /// An array literal constructed from one repeated element. /// - /// For example, `[1u8; 5]`. The first expression is the element + /// For example, `[1; 5]`. The first expression is the element /// to be repeated; the second is the number of times to repeat it. Repeat(P, P), @@ -1288,7 +1288,7 @@ pub enum LitKind { Byte(u8), /// A character literal (`'a'`) Char(char), - /// An integer literal (`1u8`) + /// An integer literal (`1`) Int(u64, LitIntType), /// A float literal (`1f64` or `1E10f64`) Float(InternedString, FloatTy), diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index cbbd5289a5a2d..c1d922ea665b1 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -168,8 +168,8 @@ pub fn mk_printer<'a>(out: Box, linewidth: usize) -> Printer<'a> { let n: usize = 3 * linewidth; debug!("mk_printer {}", linewidth); let token = vec![Token::Eof; n]; - let size = vec![0_isize; n]; - let scan_stack = vec![0_usize; n]; + let size = vec![0; n]; + let scan_stack = vec![0; n]; Printer { out: out, buf_len: n, diff --git a/src/libsyntax_ext/deriving/cmp/ord.rs b/src/libsyntax_ext/deriving/cmp/ord.rs index 2fa847ee430d8..a7e156c5f6820 100644 --- a/src/libsyntax_ext/deriving/cmp/ord.rs +++ b/src/libsyntax_ext/deriving/cmp/ord.rs @@ -11,7 +11,7 @@ use deriving::generic::*; use deriving::generic::ty::*; -use syntax::ast::{MetaItem, Expr, BinOpKind, self}; +use syntax::ast::{MetaItem, Expr, self}; use syntax::codemap::Span; use syntax::ext::base::{ExtCtxt, Annotatable}; use syntax::ext::build::AstBuilder; @@ -64,7 +64,7 @@ pub fn ordering_collapsed(cx: &mut ExtCtxt, pub fn cs_cmp(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P { - let test_id = cx.ident_of("__test"); + let test_id = cx.ident_of("cmp"); let equals_path = cx.path_global(span, cx.std_path(&["cmp", "Ordering", "Equal"])); @@ -73,36 +73,31 @@ pub fn cs_cmp(cx: &mut ExtCtxt, span: Span, /* Builds: - let __test = ::std::cmp::Ord::cmp(&self_field1, &other_field1); - if other == ::std::cmp::Ordering::Equal { - let __test = ::std::cmp::Ord::cmp(&self_field2, &other_field2); - if __test == ::std::cmp::Ordering::Equal { - ... - } else { - __test - } - } else { - __test + match ::std::cmp::Ord::cmp(&self_field1, &other_field1) { + ::std::cmp::Ordering::Equal => + match ::std::cmp::Ord::cmp(&self_field2, &other_field2) { + ::std::cmp::Ordering::Equal => { + ... + } + cmp => cmp + }, + cmp => cmp } - - FIXME #6449: These `if`s could/should be `match`es. */ cs_fold( // foldr nests the if-elses correctly, leaving the first field // as the outermost one, and the last as the innermost. false, |cx, span, old, self_f, other_fs| { - // let __test = new; - // if __test == ::std::cmp::Ordering::Equal { - // old - // } else { - // __test + // match new { + // ::std::cmp::Ordering::Equal => old, + // cmp => cmp // } let new = { let other_f = match (other_fs.len(), other_fs.get(0)) { (1, Some(o_f)) => o_f, - _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`"), + _ => cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`"), }; let args = vec![ @@ -113,20 +108,21 @@ pub fn cs_cmp(cx: &mut ExtCtxt, span: Span, cx.expr_call_global(span, cmp_path.clone(), args) }; - let assign = cx.stmt_let(span, false, test_id, new); + let eq_arm = cx.arm(span, + vec![cx.pat_enum(span, + equals_path.clone(), + vec![])], + old); + let neq_arm = cx.arm(span, + vec![cx.pat_ident(span, test_id)], + cx.expr_ident(span, test_id)); - let cond = cx.expr_binary(span, BinOpKind::Eq, - cx.expr_ident(span, test_id), - cx.expr_path(equals_path.clone())); - let if_ = cx.expr_if(span, - cond, - old, Some(cx.expr_ident(span, test_id))); - cx.expr_block(cx.block(span, vec!(assign), Some(if_))) + cx.expr_match(span, new, vec![eq_arm, neq_arm]) }, cx.expr_path(equals_path.clone()), Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| { if self_args.len() != 2 { - cx.span_bug(span, "not exactly 2 arguments in `derives(Ord)`") + cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`") } else { ordering_collapsed(cx, span, tag_tuple) } diff --git a/src/libsyntax_ext/deriving/cmp/partial_ord.rs b/src/libsyntax_ext/deriving/cmp/partial_ord.rs index e857f7d52f912..b3864a6c2e79e 100644 --- a/src/libsyntax_ext/deriving/cmp/partial_ord.rs +++ b/src/libsyntax_ext/deriving/cmp/partial_ord.rs @@ -107,41 +107,36 @@ pub fn some_ordering_collapsed(cx: &mut ExtCtxt, pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P { - let test_id = cx.ident_of("__test"); + let test_id = cx.ident_of("cmp"); let ordering = cx.path_global(span, cx.std_path(&["cmp", "Ordering", "Equal"])); - let ordering = cx.expr_path(ordering); - let equals_expr = cx.expr_some(span, ordering); + let ordering_expr = cx.expr_path(ordering.clone()); + let equals_expr = cx.expr_some(span, ordering_expr); let partial_cmp_path = cx.std_path(&["cmp", "PartialOrd", "partial_cmp"]); /* Builds: - let __test = ::std::cmp::PartialOrd::partial_cmp(&self_field1, &other_field1); - if __test == ::std::option::Option::Some(::std::cmp::Ordering::Equal) { - let __test = ::std::cmp::PartialOrd::partial_cmp(&self_field2, &other_field2); - if __test == ::std::option::Option::Some(::std::cmp::Ordering::Equal) { - ... - } else { - __test - } - } else { - __test + match ::std::cmp::PartialOrd::partial_cmp(&self_field1, &other_field1) { + ::std::option::Option::Some(::std::cmp::Ordering::Equal) => + match ::std::cmp::PartialOrd::partial_cmp(&self_field2, &other_field2) { + ::std::option::Option::Some(::std::cmp::Ordering::Equal) => { + ... + } + cmp => cmp + }, + cmp => cmp } - - FIXME #6449: These `if`s could/should be `match`es. */ cs_fold( // foldr nests the if-elses correctly, leaving the first field // as the outermost one, and the last as the innermost. false, |cx, span, old, self_f, other_fs| { - // let __test = new; - // if __test == Some(::std::cmp::Ordering::Equal) { - // old - // } else { - // __test + // match new { + // Some(::std::cmp::Ordering::Equal) => old, + // cmp => cmp // } let new = { @@ -158,15 +153,17 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span, cx.expr_call_global(span, partial_cmp_path.clone(), args) }; - let assign = cx.stmt_let(span, false, test_id, new); - - let cond = cx.expr_binary(span, BinOpKind::Eq, - cx.expr_ident(span, test_id), - equals_expr.clone()); - let if_ = cx.expr_if(span, - cond, - old, Some(cx.expr_ident(span, test_id))); - cx.expr_block(cx.block(span, vec!(assign), Some(if_))) + let eq_arm = cx.arm(span, + vec![cx.pat_some(span, + cx.pat_enum(span, + ordering.clone(), + vec![]))], + old); + let neq_arm = cx.arm(span, + vec![cx.pat_ident(span, test_id)], + cx.expr_ident(span, test_id)); + + cx.expr_match(span, new, vec![eq_arm, neq_arm]) }, equals_expr.clone(), Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| { diff --git a/src/libsyntax_ext/deriving/decodable.rs b/src/libsyntax_ext/deriving/decodable.rs index 092f8548966da..49f14c937e953 100644 --- a/src/libsyntax_ext/deriving/decodable.rs +++ b/src/libsyntax_ext/deriving/decodable.rs @@ -10,6 +10,7 @@ //! The compiler code necessary for `#[derive(Decodable)]`. See encodable.rs for more. +use deriving; use deriving::generic::*; use deriving::generic::ty::*; @@ -54,6 +55,8 @@ fn expand_deriving_decodable_imp(cx: &mut ExtCtxt, return } + let typaram = &*deriving::hygienic_type_parameter(item, "__D"); + let trait_def = TraitDef { span: span, attributes: Vec::new(), @@ -66,18 +69,17 @@ fn expand_deriving_decodable_imp(cx: &mut ExtCtxt, name: "decode", generics: LifetimeBounds { lifetimes: Vec::new(), - bounds: vec!(("__D", vec!(Path::new_( - vec!(krate, "Decoder"), None, - vec!(), true)))) + bounds: vec![(typaram, + vec![Path::new_(vec!(krate, "Decoder"), None, vec!(), true)])] }, explicit_self: None, - args: vec!(Ptr(Box::new(Literal(Path::new_local("__D"))), + args: vec!(Ptr(Box::new(Literal(Path::new_local(typaram))), Borrowed(None, Mutability::Mutable))), ret_ty: Literal(Path::new_( pathvec_std!(cx, core::result::Result), None, vec!(Box::new(Self_), Box::new(Literal(Path::new_( - vec!["__D", "Error"], None, vec![], false + vec![typaram, "Error"], None, vec![], false )))), true )), diff --git a/src/libsyntax_ext/deriving/encodable.rs b/src/libsyntax_ext/deriving/encodable.rs index 8262a04e9ce17..a05bd7869b2a9 100644 --- a/src/libsyntax_ext/deriving/encodable.rs +++ b/src/libsyntax_ext/deriving/encodable.rs @@ -88,6 +88,7 @@ //! } //! ``` +use deriving; use deriving::generic::*; use deriving::generic::ty::*; @@ -130,6 +131,8 @@ fn expand_deriving_encodable_imp(cx: &mut ExtCtxt, return; } + let typaram = &*deriving::hygienic_type_parameter(item, "__S"); + let trait_def = TraitDef { span: span, attributes: Vec::new(), @@ -142,18 +145,17 @@ fn expand_deriving_encodable_imp(cx: &mut ExtCtxt, name: "encode", generics: LifetimeBounds { lifetimes: Vec::new(), - bounds: vec!(("__S", vec!(Path::new_( - vec!(krate, "Encoder"), None, - vec!(), true)))) + bounds: vec![(typaram, + vec![Path::new_(vec![krate, "Encoder"], None, vec!(), true)])] }, explicit_self: borrowed_explicit_self(), - args: vec!(Ptr(Box::new(Literal(Path::new_local("__S"))), + args: vec!(Ptr(Box::new(Literal(Path::new_local(typaram))), Borrowed(None, Mutability::Mutable))), ret_ty: Literal(Path::new_( pathvec_std!(cx, core::result::Result), None, vec!(Box::new(Tuple(Vec::new())), Box::new(Literal(Path::new_( - vec!["__S", "Error"], None, vec![], false + vec![typaram, "Error"], None, vec![], false )))), true )), diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index c0237a5d29a41..93fcfa4cc6372 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -156,14 +156,14 @@ //! //! ```{.text} //! EnumNonMatchingCollapsed( -//! vec![, ], +//! vec![, ], //! &[, ], -//! &[, ]) +//! &[, ]) //! ``` //! //! It is the same for when the arguments are flipped to `C1 {x}` and //! `C0(a)`; the only difference is what the values of the identifiers -//! and will +//! and will //! be in the generated code. //! //! `EnumNonMatchingCollapsed` deliberately provides far less information @@ -209,6 +209,8 @@ use syntax::ptr::P; use self::ty::{LifetimeBounds, Path, Ptr, PtrTy, Self_, Ty}; +use deriving; + pub mod ty; pub struct TraitDef<'a> { @@ -741,7 +743,7 @@ impl<'a> TraitDef<'a> { fn find_repr_type_name(diagnostic: &Handler, type_attrs: &[ast::Attribute]) -> &'static str { - let mut repr_type_name = "i32"; + let mut repr_type_name = "i64"; for a in type_attrs { for r in &attr::find_repr_attrs(diagnostic, a) { repr_type_name = match *r { @@ -826,7 +828,7 @@ impl<'a> MethodDef<'a> { for (i, ty) in self.args.iter().enumerate() { let ast_ty = ty.to_ty(cx, trait_.span, type_ident, generics); - let ident = cx.ident_of(&format!("__arg_{}", i)); + let ident = cx.ident_of(&format!("arg_{}", i)); arg_tys.push((ident, ast_ty)); let arg_expr = cx.expr_ident(trait_.span, ident); @@ -911,12 +913,12 @@ impl<'a> MethodDef<'a> { /// /// // equivalent to: /// impl PartialEq for A { - /// fn eq(&self, __arg_1: &A) -> bool { + /// fn eq(&self, arg_1: &A) -> bool { /// match *self { - /// A {x: ref __self_0_0, y: ref __self_0_1} => { - /// match *__arg_1 { - /// A {x: ref __self_1_0, y: ref __self_1_1} => { - /// __self_0_0.eq(__self_1_0) && __self_0_1.eq(__self_1_1) + /// A {x: ref self_0_0, y: ref self_0_1} => { + /// match *arg_1 { + /// A {x: ref self_1_0, y: ref self_1_1} => { + /// self_0_0.eq(self_1_0) && self_0_1.eq(self_1_1) /// } /// } /// } @@ -942,7 +944,7 @@ impl<'a> MethodDef<'a> { trait_.create_struct_pattern(cx, struct_path, struct_def, - &format!("__self_{}", + &format!("self_{}", i), ast::Mutability::Immutable); patterns.push(pat); @@ -1020,14 +1022,14 @@ impl<'a> MethodDef<'a> { /// // is equivalent to /// /// impl PartialEq for A { - /// fn eq(&self, __arg_1: &A) -> ::bool { - /// match (&*self, &*__arg_1) { + /// fn eq(&self, arg_1: &A) -> ::bool { + /// match (&*self, &*arg_1) { /// (&A1, &A1) => true, - /// (&A2(ref __self_0), - /// &A2(ref __arg_1_0)) => (*__self_0).eq(&(*__arg_1_0)), + /// (&A2(ref self_0), + /// &A2(ref arg_1_0)) => (*self_0).eq(&(*arg_1_0)), /// _ => { - /// let __self_vi = match *self { A1(..) => 0, A2(..) => 1 }; - /// let __arg_1_vi = match *__arg_1 { A1(..) => 0, A2(..) => 1 }; + /// let self_vi = match *self { A1(..) => 0, A2(..) => 1 }; + /// let arg_1_vi = match *arg_1 { A1(..) => 0, A2(..) => 1 }; /// false /// } /// } @@ -1035,10 +1037,10 @@ impl<'a> MethodDef<'a> { /// } /// ``` /// - /// (Of course `__self_vi` and `__arg_1_vi` are unused for + /// (Of course `self_vi` and `arg_1_vi` are unused for /// `PartialEq`, and those subcomputations will hopefully be removed - /// as their results are unused. The point of `__self_vi` and - /// `__arg_1_vi` is for `PartialOrd`; see #15503.) + /// as their results are unused. The point of `self_vi` and + /// `arg_1_vi` is for `PartialOrd`; see #15503.) fn expand_enum_method_body<'b>(&self, cx: &mut ExtCtxt, trait_: &TraitDef<'b>, @@ -1069,14 +1071,14 @@ impl<'a> MethodDef<'a> { /// for each of the self-args, carried in precomputed variables. /// ```{.text} - /// let __self0_vi = unsafe { + /// let self0_vi = unsafe { /// std::intrinsics::discriminant_value(&self) } as i32; - /// let __self1_vi = unsafe { - /// std::intrinsics::discriminant_value(&__arg1) } as i32; - /// let __self2_vi = unsafe { - /// std::intrinsics::discriminant_value(&__arg2) } as i32; + /// let self1_vi = unsafe { + /// std::intrinsics::discriminant_value(&arg1) } as i32; + /// let self2_vi = unsafe { + /// std::intrinsics::discriminant_value(&arg2) } as i32; /// - /// if __self0_vi == __self1_vi && __self0_vi == __self2_vi && ... { + /// if self0_vi == self1_vi && self0_vi == self2_vi && ... { /// match (...) { /// (Variant1, Variant1, ...) => Body1 /// (Variant2, Variant2, ...) => Body2, @@ -1104,9 +1106,9 @@ impl<'a> MethodDef<'a> { let self_arg_names = self_args.iter().enumerate() .map(|(arg_count, _self_arg)| { if arg_count == 0 { - "__self".to_string() + "self".to_string() } else { - format!("__arg_{}", arg_count) + format!("arg_{}", arg_count) } }) .collect::>(); @@ -1243,17 +1245,17 @@ impl<'a> MethodDef<'a> { // with three Self args, builds three statements: // // ``` - // let __self0_vi = unsafe { + // let self0_vi = unsafe { // std::intrinsics::discriminant_value(&self) } as i32; - // let __self1_vi = unsafe { - // std::intrinsics::discriminant_value(&__arg1) } as i32; - // let __self2_vi = unsafe { - // std::intrinsics::discriminant_value(&__arg2) } as i32; + // let self1_vi = unsafe { + // std::intrinsics::discriminant_value(&arg1) } as i32; + // let self2_vi = unsafe { + // std::intrinsics::discriminant_value(&arg2) } as i32; // ``` let mut index_let_stmts: Vec = Vec::new(); //We also build an expression which checks whether all discriminants are equal - // discriminant_test = __self0_vi == __self1_vi && __self0_vi == __self2_vi && ... + // discriminant_test = self0_vi == self1_vi && self0_vi == self2_vi && ... let mut discriminant_test = cx.expr_bool(sp, true); let target_type_name = @@ -1261,15 +1263,11 @@ impl<'a> MethodDef<'a> { let mut first_ident = None; for (&ident, self_arg) in vi_idents.iter().zip(&self_args) { - let path = cx.std_path(&["intrinsics", "discriminant_value"]); - let call = cx.expr_call_global( - sp, path, vec![cx.expr_addr_of(sp, self_arg.clone())]); - let variant_value = cx.expr_block(P(ast::Block { - stmts: vec![], - expr: Some(call), - id: ast::DUMMY_NODE_ID, - rules: ast::BlockCheckMode::Unsafe(ast::CompilerGenerated), - span: sp })); + let self_addr = cx.expr_addr_of(sp, self_arg.clone()); + let variant_value = deriving::call_intrinsic(cx, + sp, + "discriminant_value", + vec![self_addr]); let target_ty = cx.ty_ident(sp, cx.ident_of(target_type_name)); let variant_disr = cx.expr_cast(sp, variant_value, target_ty); @@ -1297,22 +1295,15 @@ impl<'a> MethodDef<'a> { //Since we know that all the arguments will match if we reach the match expression we //add the unreachable intrinsics as the result of the catch all which should help llvm //in optimizing it - let path = cx.std_path(&["intrinsics", "unreachable"]); - let call = cx.expr_call_global( - sp, path, vec![]); - let unreachable = cx.expr_block(P(ast::Block { - stmts: vec![], - expr: Some(call), - id: ast::DUMMY_NODE_ID, - rules: ast::BlockCheckMode::Unsafe(ast::CompilerGenerated), - span: sp })); - match_arms.push(cx.arm(sp, vec![cx.pat_wild(sp)], unreachable)); + match_arms.push(cx.arm(sp, + vec![cx.pat_wild(sp)], + deriving::call_intrinsic(cx, sp, "unreachable", vec![]))); // Final wrinkle: the self_args are expressions that deref // down to desired l-values, but we cannot actually deref // them when they are fed as r-values into a tuple // expression; here add a layer of borrowing, turning - // `(*self, *__arg_0, ...)` into `(&*self, &*__arg_0, ...)`. + // `(*self, *arg_0, ...)` into `(&*self, &*arg_0, ...)`. let borrowed_self_args = self_args.move_map(|self_arg| cx.expr_addr_of(sp, self_arg)); let match_arg = cx.expr(sp, ast::ExprKind::Tup(borrowed_self_args)); @@ -1326,7 +1317,7 @@ impl<'a> MethodDef<'a> { // } // } // else { - // + // // } let all_match = cx.expr_match(sp, match_arg, match_arms); let arm_expr = cx.expr_if(sp, discriminant_test, all_match, Some(arm_expr)); @@ -1350,8 +1341,8 @@ impl<'a> MethodDef<'a> { // error-prone, since the catch-all as defined above would // generate code like this: // - // _ => { let __self0 = match *self { }; - // let __self1 = match *__arg_0 { }; + // _ => { let self0 = match *self { }; + // let self1 = match *arg_0 { }; // } // // Which is yields bindings for variables which type @@ -1382,7 +1373,7 @@ impl<'a> MethodDef<'a> { // derive Debug on such a type could here generate code // that needs the feature gate enabled.) - cx.expr_unreachable(sp) + deriving::call_intrinsic(cx, sp, "unreachable", vec![]) } else { @@ -1390,7 +1381,7 @@ impl<'a> MethodDef<'a> { // down to desired l-values, but we cannot actually deref // them when they are fed as r-values into a tuple // expression; here add a layer of borrowing, turning - // `(*self, *__arg_0, ...)` into `(&*self, &*__arg_0, ...)`. + // `(*self, *arg_0, ...)` into `(&*self, &*arg_0, ...)`. let borrowed_self_args = self_args.move_map(|self_arg| cx.expr_addr_of(sp, self_arg)); let match_arg = cx.expr(sp, ast::ExprKind::Tup(borrowed_self_args)); cx.expr_match(sp, match_arg, match_arms) @@ -1604,8 +1595,8 @@ pub fn cs_fold(use_foldl: bool, /// process the collected results. i.e. /// /// ```ignore -/// f(cx, span, vec![self_1.method(__arg_1_1, __arg_2_1), -/// self_2.method(__arg_1_2, __arg_2_2)]) +/// f(cx, span, vec![self_1.method(arg_1_1, arg_2_1), +/// self_2.method(arg_1_2, arg_2_2)]) /// ``` #[inline] pub fn cs_same_method(f: F, diff --git a/src/libsyntax_ext/deriving/hash.rs b/src/libsyntax_ext/deriving/hash.rs index bf8aa8fb23deb..c37ae116d379b 100644 --- a/src/libsyntax_ext/deriving/hash.rs +++ b/src/libsyntax_ext/deriving/hash.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use deriving; use deriving::generic::*; use deriving::generic::ty::*; @@ -26,7 +27,10 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt, let path = Path::new_(pathvec_std!(cx, core::hash::Hash), None, vec!(), true); - let arg = Path::new_local("__H"); + + let typaram = &*deriving::hygienic_type_parameter(item, "__H"); + + let arg = Path::new_local(typaram); let hash_trait_def = TraitDef { span: span, attributes: Vec::new(), @@ -39,7 +43,7 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt, name: "hash", generics: LifetimeBounds { lifetimes: Vec::new(), - bounds: vec![("__H", + bounds: vec![(typaram, vec![path_std!(cx, core::hash::Hasher)])], }, explicit_self: borrowed_explicit_self(), @@ -77,15 +81,13 @@ fn hash_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) let fields = match *substr.fields { Struct(_, ref fs) => fs, - EnumMatching(index, variant, ref fs) => { - // Determine the discriminant. We will feed this value to the byte - // iteration function. - let discriminant = match variant.node.disr_expr { - Some(ref d) => d.clone(), - None => cx.expr_usize(trait_span, index) - }; + EnumMatching(_, _, ref fs) => { + let variant_value = deriving::call_intrinsic(cx, + trait_span, + "discriminant_value", + vec![cx.expr_self(trait_span)]); - stmts.push(call_hash(trait_span, discriminant)); + stmts.push(call_hash(trait_span, variant_value)); fs } diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index 4e2142f1fb482..615cb1de0f475 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -9,11 +9,8 @@ // except according to those terms. //! The compiler code necessary to implement the `#[derive]` extensions. -//! -//! FIXME (#2810): hygiene. Search for "__" strings (in other files too). We also assume "extra" is -//! the standard library, and "std" is the core library. -use syntax::ast::{MetaItem, MetaItemKind}; +use syntax::ast::{MetaItem, MetaItemKind, self}; use syntax::attr::AttrMetaMethods; use syntax::ext::base::{ExtCtxt, SyntaxEnv, Annotatable}; use syntax::ext::base::{MultiDecorator, MultiItemDecorator, MultiModifier}; @@ -21,6 +18,7 @@ use syntax::ext::build::AstBuilder; use syntax::feature_gate; use syntax::codemap::Span; use syntax::parse::token::{intern, intern_and_get_ident}; +use syntax::ptr::P; macro_rules! pathvec { ($($x:ident)::+) => ( @@ -197,3 +195,43 @@ fn warn_if_deprecated(ecx: &mut ExtCtxt, sp: Span, name: &str) { name, replacement)); } } + +/// Construct a name for the inner type parameter that can't collide with any type parameters of +/// the item. This is achieved by starting with a base and then concatenating the names of all +/// other type parameters. +// FIXME(aburka): use real hygiene when that becomes possible +fn hygienic_type_parameter(item: &Annotatable, base: &str) -> String { + let mut typaram = String::from(base); + if let Annotatable::Item(ref item) = *item { + match item.node { + ast::ItemKind::Struct(_, ast::Generics { ref ty_params, .. }) | + ast::ItemKind::Enum(_, ast::Generics { ref ty_params, .. }) => { + + for ty in ty_params.iter() { + typaram.push_str(&ty.ident.name.as_str()); + } + } + + _ => {} + } + } + + typaram +} + +/// Constructs an expression that calls an intrinsic +fn call_intrinsic(cx: &ExtCtxt, + span: Span, + intrinsic: &str, + args: Vec>) -> P { + let path = cx.std_path(&["intrinsics", intrinsic]); + let call = cx.expr_call_global(span, path, args); + + cx.expr_block(P(ast::Block { + stmts: vec![], + expr: Some(call), + id: ast::DUMMY_NODE_ID, + rules: ast::BlockCheckMode::Unsafe(ast::CompilerGenerated), + span: span })) +} + diff --git a/src/test/run-pass-fulldeps/derive-no-std.rs b/src/test/auxiliary/derive-no-std.rs similarity index 64% rename from src/test/run-pass-fulldeps/derive-no-std.rs rename to src/test/auxiliary/derive-no-std.rs index 78e9da001f799..f083e10bfdb32 100644 --- a/src/test/run-pass-fulldeps/derive-no-std.rs +++ b/src/test/auxiliary/derive-no-std.rs @@ -8,32 +8,33 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(rand, collections, rustc_private)] -#![no_std] +// no-prefer-dynamic -extern crate rand; -extern crate serialize as rustc_serialize; -extern crate collections; +#![crate_type = "rlib"] +#![no_std] // Issue #16803 #[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Copy)] -struct Foo { - x: u32, +pub struct Foo { + pub x: u32, } #[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Copy)] -enum Bar { +pub enum Bar { Qux, Quux(u32), } -enum Baz { A=0, B=5, } +#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord, + Debug, Copy)] +pub enum Void {} +#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord, + Debug, Copy)] +pub struct Empty; +#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord, + Debug, Copy)] +pub struct AlsoEmpty {} -fn main() { - Foo { x: 0 }; - Bar::Quux(3); - Baz::A; -} diff --git a/src/test/compile-fail/issue-30580.rs b/src/test/compile-fail/issue-30580.rs new file mode 100644 index 0000000000000..88d4aef6d9ddc --- /dev/null +++ b/src/test/compile-fail/issue-30580.rs @@ -0,0 +1,27 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that we do not see uninformative region-related errors +// when we get some basic type-checking failure. See #30580. + +pub struct Foo { a: u32 } +pub struct Pass<'a, 'tcx: 'a>(&'a mut &'a (), &'a &'tcx ()); + +impl<'a, 'tcx> Pass<'a, 'tcx> +{ + pub fn tcx(&self) -> &'a &'tcx () { self.1 } + fn lol(&mut self, b: &Foo) + { + b.c; //~ ERROR no field with that name was found + self.tcx(); + } +} + +fn main() {} diff --git a/src/test/compile-fail/lexical-scopes.rs b/src/test/compile-fail/lexical-scopes.rs new file mode 100644 index 0000000000000..dbcd3f32f3b66 --- /dev/null +++ b/src/test/compile-fail/lexical-scopes.rs @@ -0,0 +1,23 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct T { i: i32 } +fn f() { + let t = T { i: 0 }; //~ ERROR `T` does not name a structure +} + +mod Foo { + pub fn f() {} +} +fn g() { + Foo::f(); //~ ERROR no associated item named `f` +} + +fn main() {} diff --git a/src/test/run-pass/cci_nested_exe.rs b/src/test/run-pass/cci_nested_exe.rs index e4f4a4f3a576c..b40c29dd71529 100644 --- a/src/test/run-pass/cci_nested_exe.rs +++ b/src/test/run-pass/cci_nested_exe.rs @@ -11,8 +11,6 @@ // aux-build:cci_nested_lib.rs -#![feature(globs)] - extern crate cci_nested_lib; use cci_nested_lib::*; diff --git a/src/test/run-pass/derive-no-std.rs b/src/test/run-pass/derive-no-std.rs new file mode 100644 index 0000000000000..0cbe4f4ebd0ed --- /dev/null +++ b/src/test/run-pass/derive-no-std.rs @@ -0,0 +1,22 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:derive-no-std.rs + +extern crate derive_no_std; +use derive_no_std::*; + +fn main() { + let f = Foo { x: 0 }; + assert_eq!(f.clone(), Foo::default()); + + assert!(Bar::Qux < Bar::Quux(42)); +} + diff --git a/src/test/run-pass/deriving-hash.rs b/src/test/run-pass/deriving-hash.rs index 69e9816ab9486..c40d0683657a8 100644 --- a/src/test/run-pass/deriving-hash.rs +++ b/src/test/run-pass/deriving-hash.rs @@ -12,6 +12,7 @@ #![feature(hash_default)] use std::hash::{Hash, SipHasher, Hasher}; +use std::mem::size_of; #[derive(Hash)] struct Person { @@ -20,12 +21,34 @@ struct Person { phone: usize, } +#[derive(Hash)] +enum E { A=1, B } + +// test for hygiene name collisions +#[derive(Hash)] struct __H__H; +#[derive(Hash)] enum Collision<__H> { __H { __H__H: __H } } + fn hash(t: &T) -> u64 { let mut s = SipHasher::new_with_keys(0, 0); t.hash(&mut s); s.finish() } +struct FakeHasher<'a>(&'a mut Vec); +impl<'a> Hasher for FakeHasher<'a> { + fn finish(&self) -> u64 { + unimplemented!() + } + + fn write(&mut self, bytes: &[u8]) { + self.0.extend(bytes); + } +} + +fn fake_hash(v: &mut Vec, e: E) { + e.hash(&mut FakeHasher(v)); +} + fn main() { let person1 = Person { id: 5, @@ -39,4 +62,11 @@ fn main() { }; assert_eq!(hash(&person1), hash(&person1)); assert!(hash(&person1) != hash(&person2)); + + // test #21714 + let mut va = vec![]; + let mut vb = vec![]; + fake_hash(&mut va, E::A); + fake_hash(&mut vb, E::B); + assert!(va != vb); } diff --git a/src/test/run-pass/enum-discrim-autosizing.rs b/src/test/run-pass/enum-discrim-autosizing.rs index 99e44735d0f03..f027689a64a54 100644 --- a/src/test/run-pass/enum-discrim-autosizing.rs +++ b/src/test/run-pass/enum-discrim-autosizing.rs @@ -46,6 +46,7 @@ enum Ei64 { Bi64 = 0x8000_0000 } +#[derive(PartialEq)] enum Eu64 { Au64 = 0, Bu64 = 0x8000_0000_0000_0000 @@ -60,4 +61,7 @@ pub fn main() { assert_eq!(size_of::(), 4); assert_eq!(size_of::(), 8); assert_eq!(size_of::(), 8); + + // ensure no i32 collisions + assert!(Eu64::Au64 != Eu64::Bu64); } diff --git a/src/test/rustdoc/inline_local/issue-28537.rs b/src/test/rustdoc/inline_local/issue-28537.rs new file mode 100644 index 0000000000000..b38e104b7b4ee --- /dev/null +++ b/src/test/rustdoc/inline_local/issue-28537.rs @@ -0,0 +1,27 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[doc(hidden)] +pub mod foo { + pub struct Foo; +} + +mod bar { + pub use self::bar::Bar; + mod bar { + pub struct Bar; + } +} + +// @has issue_28537/struct.Foo.html +pub use foo::Foo; + +// @has issue_28537/struct.Bar.html +pub use self::bar::Bar; diff --git a/src/test/rustdoc/inline_local/please_inline.rs b/src/test/rustdoc/inline_local/please_inline.rs new file mode 100644 index 0000000000000..d237ab8dab01a --- /dev/null +++ b/src/test/rustdoc/inline_local/please_inline.rs @@ -0,0 +1,29 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub mod foo { + pub struct Foo; +} + +// @has please_inline/a/index.html +pub mod a { + // @!has - 'pub use foo::' + // @has please_inline/a/struct.Foo.html + #[doc(inline)] + pub use foo::Foo; +} + +// @has please_inline/b/index.html +pub mod b { + // @has - 'pub use foo::' + // @!has please_inline/b/struct.Foo.html + #[feature(inline)] + pub use foo::Foo; +} diff --git a/src/test/rustdoc/recursion1.rs b/src/test/rustdoc/recursion1.rs index 7505d20566dbb..00f7d90fabc38 100644 --- a/src/test/rustdoc/recursion1.rs +++ b/src/test/rustdoc/recursion1.rs @@ -9,7 +9,6 @@ // except according to those terms. #![crate_type = "lib"] -#![feature(globs)] mod m { pub use self::a::Foo; diff --git a/src/test/rustdoc/recursion2.rs b/src/test/rustdoc/recursion2.rs index 7505d20566dbb..00f7d90fabc38 100644 --- a/src/test/rustdoc/recursion2.rs +++ b/src/test/rustdoc/recursion2.rs @@ -9,7 +9,6 @@ // except according to those terms. #![crate_type = "lib"] -#![feature(globs)] mod m { pub use self::a::Foo; diff --git a/src/test/rustdoc/recursion3.rs b/src/test/rustdoc/recursion3.rs index 62a13f76ca4f0..1d9b903a27920 100644 --- a/src/test/rustdoc/recursion3.rs +++ b/src/test/rustdoc/recursion3.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(globs)] - pub mod longhands { pub use super::*;