mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 08:13:41 +00:00
Auto merge of #68933 - Dylan-DPC:rollup-akz13kj, r=Dylan-DPC
Rollup of 7 pull requests Successful merges: - #68164 (Selectively disable sanitizer instrumentation) - #68413 (Add GitHub issue templates) - #68889 (Move the `hir().krate()` method to a query and remove the `Krate` dep node) - #68909 (Respect --nocapture in panic=abort test mode) - #68910 (Add myself to .mailmap) - #68919 (Remove HashStable impl for ast::Lifetime) - #68928 (clean up E0276 explanation) Failed merges: r? @ghost
This commit is contained in:
commit
a29424a226
4
.github/ISSUE_TEMPLATE/blank_issue.md
vendored
Normal file
4
.github/ISSUE_TEMPLATE/blank_issue.md
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
---
|
||||
name: Blank Issue
|
||||
about: Create a blank issue.
|
||||
---
|
44
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
44
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
---
|
||||
name: Bug Report
|
||||
about: Create a bug report for Rust.
|
||||
labels: C-bug
|
||||
---
|
||||
<!--
|
||||
Thank you for filing a bug report! 🐛 Please provide a short summary of the bug,
|
||||
along with any information you feel relevant to replicating the bug.
|
||||
-->
|
||||
|
||||
I tried this code:
|
||||
|
||||
```rust
|
||||
<code>
|
||||
```
|
||||
|
||||
I expected to see this happen: *explanation*
|
||||
|
||||
Instead, this happened: *explanation*
|
||||
|
||||
### Meta
|
||||
<!--
|
||||
If you're using the stable version of the compiler, you should also check if the
|
||||
bug also exists in the beta or nightly versions.
|
||||
-->
|
||||
|
||||
`rustc --version --verbose`:
|
||||
```
|
||||
<version>
|
||||
```
|
||||
|
||||
<!--
|
||||
Include a backtrace in the code block by setting `RUST_BACKTRACE=1` in your
|
||||
environment. E.g. `RUST_BACKTRACE=1 cargo build`.
|
||||
-->
|
||||
<details><summary>Backtrace</summary>
|
||||
<p>
|
||||
|
||||
```
|
||||
<backtrace>
|
||||
```
|
||||
|
||||
</p>
|
||||
</details>
|
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: Rust Programming Language Forum
|
||||
url: https://users.rust-lang.org
|
||||
about: Please ask and answer questions about Rust here.
|
52
.github/ISSUE_TEMPLATE/ice.md
vendored
Normal file
52
.github/ISSUE_TEMPLATE/ice.md
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
---
|
||||
name: Internal Compiler Error
|
||||
about: Create a report for an internal compiler error in rustc.
|
||||
labels: C-bug, I-ICE, T-compiler
|
||||
---
|
||||
<!--
|
||||
Thank you for finding an Internal Compiler Error! 🧊 If possible, try to provide
|
||||
a minimal verifiable example. You can read "Rust Bug Minimization Patterns" for
|
||||
how to create smaller examples.
|
||||
|
||||
http://blog.pnkfx.org/blog/2019/11/18/rust-bug-minimization-patterns/
|
||||
|
||||
-->
|
||||
|
||||
### Code
|
||||
|
||||
```
|
||||
<code>
|
||||
```
|
||||
|
||||
|
||||
### Meta
|
||||
<!--
|
||||
If you're using the stable version of the compiler, you should also check if the
|
||||
bug also exists in the beta or nightly versions.
|
||||
-->
|
||||
|
||||
`rustc --version --verbose`:
|
||||
```
|
||||
<version>
|
||||
```
|
||||
|
||||
### Error output
|
||||
|
||||
```
|
||||
<output>
|
||||
```
|
||||
|
||||
<!--
|
||||
Include a backtrace in the code block by setting `RUST_BACKTRACE=1` in your
|
||||
environment. E.g. `RUST_BACKTRACE=1 cargo build`.
|
||||
-->
|
||||
<details><summary><strong>Backtrace</strong></summary>
|
||||
<p>
|
||||
|
||||
```
|
||||
<backtrace>
|
||||
```
|
||||
|
||||
</p>
|
||||
</details>
|
||||
|
58
.github/ISSUE_TEMPLATE/tracking_issue.md
vendored
Normal file
58
.github/ISSUE_TEMPLATE/tracking_issue.md
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
---
|
||||
name: Tracking Issue
|
||||
about: A tracking issue for a feature in Rust.
|
||||
title: Tracking Issue for XXX
|
||||
labels: C-tracking-issue
|
||||
---
|
||||
<!--
|
||||
Thank you for creating a tracking issue! 📜 Tracking issues are for tracking a
|
||||
feature from implementation to stabilisation. Make sure to include the relevant
|
||||
RFC for the feature if it has one. Otherwise provide a short summary of the
|
||||
feature and link any relevant PRs or issues, and remove any sections that are
|
||||
not relevant to the feature.
|
||||
|
||||
Remember to add team labels to the tracking issue.
|
||||
For a language team feature, this would e.g., be `T-lang`.
|
||||
Such a feature should also be labeled with e.g., `F-my_feature`.
|
||||
This label is used to associate issues (e.g., bugs and design questions) to the feature.
|
||||
-->
|
||||
|
||||
This is a tracking issue for the RFC "XXX" (rust-lang/rfcs#NNN).
|
||||
The feature gate for the issue is `#![feature(FFF)]`.
|
||||
|
||||
### About tracking issues
|
||||
|
||||
Tracking issues are used to record the overall progress of implementation.
|
||||
They are also uses as hubs connecting to other relevant issues, e.g., bugs or open design questions.
|
||||
A tracking issue is however *not* meant for large scale discussion, questions, or bug reports about a feature.
|
||||
Instead, open a dedicated issue for the specific matter and add the relevant feature gate label.
|
||||
|
||||
### Steps
|
||||
<!--
|
||||
Include each step required to complete the feature. Typically this is a PR
|
||||
implementing a feature, followed by a PR that stabilises the feature. However
|
||||
for larger features an implementation could be broken up into multiple PRs.
|
||||
-->
|
||||
|
||||
- [ ] Implement the RFC (cc @rust-lang/XXX -- can anyone write up mentoring
|
||||
instructions?)
|
||||
- [ ] Adjust documentation ([see instructions on rustc-guide][doc-guide])
|
||||
- [ ] Stabilization PR ([see instructions on rustc-guide][stabilization-guide])
|
||||
|
||||
[stabilization-guide]: https://rust-lang.github.io/rustc-guide/stabilization_guide.html#stabilization-pr
|
||||
[doc-guide]: https://rust-lang.github.io/rustc-guide/stabilization_guide.html#documentation-prs
|
||||
|
||||
### Unresolved Questions
|
||||
<!--
|
||||
Include any open questions that need to be answered before the feature can be
|
||||
stabilised.
|
||||
-->
|
||||
|
||||
XXX --- list all the "unresolved questions" found in the RFC to ensure they are
|
||||
not forgotten
|
||||
|
||||
### Implementation history
|
||||
|
||||
<!--
|
||||
Include a list of all the PRs that were involved in implementing the feature.
|
||||
-->
|
1
.mailmap
1
.mailmap
@ -100,6 +100,7 @@ Graydon Hoare <graydon@pobox.com> Graydon Hoare <graydon@mozilla.com>
|
||||
Guillaume Gomez <guillaume1.gomez@gmail.com>
|
||||
Guillaume Gomez <guillaume1.gomez@gmail.com> ggomez <ggomez@ggo.ifr.lan>
|
||||
Guillaume Gomez <guillaume1.gomez@gmail.com> Guillaume Gomez <ggomez@ggo.ifr.lan>
|
||||
Hanna Kruppe <hanna.kruppe@gmail.com> <robin.kruppe@gmail.com>
|
||||
Heather <heather@cynede.net> <Cynede@Gentoo.org>
|
||||
Heather <heather@cynede.net> <Heather@cynede.net>
|
||||
Herman J. Radtke III <herman@hermanradtke.com> Herman J. Radtke III <hermanradtke@gmail.com>
|
||||
|
29
src/doc/unstable-book/src/language-features/no-sanitize.md
Normal file
29
src/doc/unstable-book/src/language-features/no-sanitize.md
Normal file
@ -0,0 +1,29 @@
|
||||
# `no_sanitize`
|
||||
|
||||
The tracking issue for this feature is: [#39699]
|
||||
|
||||
[#39699]: https://github.com/rust-lang/rust/issues/39699
|
||||
|
||||
------------------------
|
||||
|
||||
The `no_sanitize` attribute can be used to selectively disable sanitizer
|
||||
instrumentation in an annotated function. This might be useful to: avoid
|
||||
instrumentation overhead in a performance critical function, or avoid
|
||||
instrumenting code that contains constructs unsupported by given sanitizer.
|
||||
|
||||
The precise effect of this annotation depends on particular sanitizer in use.
|
||||
For example, with `no_sanitize(thread)`, the thread sanitizer will no longer
|
||||
instrument non-atomic store / load operations, but it will instrument atomic
|
||||
operations to avoid reporting false positives and provide meaning full stack
|
||||
traces.
|
||||
|
||||
## Examples
|
||||
|
||||
``` rust
|
||||
#![feature(no_sanitize)]
|
||||
|
||||
#[no_sanitize(address)]
|
||||
fn foo() {
|
||||
// ...
|
||||
}
|
||||
```
|
@ -127,7 +127,7 @@ macro_rules! arena_types {
|
||||
[] tys: rustc::ty::TyS<$tcx>,
|
||||
|
||||
// HIR types
|
||||
[few] hir_forest: rustc::hir::map::Forest<$tcx>,
|
||||
[few] hir_krate: rustc_hir::Crate<$tcx>,
|
||||
[] arm: rustc_hir::Arm<$tcx>,
|
||||
[] attribute: syntax::ast::Attribute,
|
||||
[] block: rustc_hir::Block<$tcx>,
|
||||
|
@ -35,7 +35,7 @@
|
||||
//! "infer" some properties for each kind of `DepNode`:
|
||||
//!
|
||||
//! * Whether a `DepNode` of a given kind has any parameters at all. Some
|
||||
//! `DepNode`s, like `Krate`, represent global concepts with only one value.
|
||||
//! `DepNode`s, like `AllLocalTraitImpls`, represent global concepts with only one value.
|
||||
//! * Whether it is possible, in principle, to reconstruct a query key from a
|
||||
//! given `DepNode`. Many `DepKind`s only require a single `DefId` parameter,
|
||||
//! in which case it is possible to map the node's fingerprint back to the
|
||||
@ -400,19 +400,6 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx>
|
||||
// We use this for most things when incr. comp. is turned off.
|
||||
[] Null,
|
||||
|
||||
// Represents the `Krate` as a whole (the `hir::Krate` value) (as
|
||||
// distinct from the krate module). This is basically a hash of
|
||||
// the entire krate, so if you read from `Krate` (e.g., by calling
|
||||
// `tcx.hir().krate()`), we will have to assume that any change
|
||||
// means that you need to be recompiled. This is because the
|
||||
// `Krate` value gives you access to all other items. To avoid
|
||||
// this fate, do not call `tcx.hir().krate()`; instead, prefer
|
||||
// wrappers like `tcx.visit_all_items_in_krate()`. If there is no
|
||||
// suitable wrapper, you can use `tcx.dep_graph.ignore()` to gain
|
||||
// access to the krate, but you must remember to add suitable
|
||||
// edges yourself for the individual items that you read.
|
||||
[eval_always] Krate,
|
||||
|
||||
// Represents the body of a function or method. The def-id is that of the
|
||||
// function/method.
|
||||
[eval_always] HirBody(DefId),
|
||||
|
@ -223,12 +223,9 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
|
||||
(commandline_args_hash, crate_disambiguator.to_fingerprint()),
|
||||
);
|
||||
|
||||
let (_, crate_hash) = input_dep_node_and_hash(
|
||||
self.dep_graph,
|
||||
&mut self.hcx,
|
||||
DepNode::new_no_params(DepKind::Krate),
|
||||
crate_hash_input,
|
||||
);
|
||||
let mut stable_hasher = StableHasher::new();
|
||||
crate_hash_input.hash_stable(&mut self.hcx, &mut stable_hasher);
|
||||
let crate_hash: Fingerprint = stable_hasher.finish();
|
||||
|
||||
let svh = Svh::new(crate_hash.to_smaller_hash());
|
||||
(self.map, svh)
|
||||
|
@ -12,7 +12,7 @@ pub fn check_crate(hir_map: &Map<'_>) {
|
||||
|
||||
let errors = Lock::new(Vec::new());
|
||||
|
||||
par_iter(&hir_map.krate().modules).for_each(|(module_id, _)| {
|
||||
par_iter(&hir_map.krate.modules).for_each(|(module_id, _)| {
|
||||
let local_def_id = hir_map.local_def_id(*module_id);
|
||||
hir_map.visit_item_likes_in_module(
|
||||
local_def_id,
|
||||
|
@ -129,30 +129,6 @@ impl<'hir> Entry<'hir> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Stores a crate and any number of inlined items from other crates.
|
||||
pub struct Forest<'hir> {
|
||||
krate: Crate<'hir>,
|
||||
pub dep_graph: DepGraph,
|
||||
}
|
||||
|
||||
impl Forest<'hir> {
|
||||
pub fn new(krate: Crate<'hir>, dep_graph: &DepGraph) -> Forest<'hir> {
|
||||
Forest { krate, dep_graph: dep_graph.clone() }
|
||||
}
|
||||
|
||||
pub fn krate(&self) -> &Crate<'hir> {
|
||||
self.dep_graph.read(DepNode::new_no_params(DepKind::Krate));
|
||||
&self.krate
|
||||
}
|
||||
|
||||
/// This is used internally in the dependency tracking system.
|
||||
/// Use the `krate` method to ensure your dependency on the
|
||||
/// crate is tracked.
|
||||
pub fn untracked_krate(&self) -> &Crate<'hir> {
|
||||
&self.krate
|
||||
}
|
||||
}
|
||||
|
||||
/// This type is effectively a `HashMap<HirId, Entry<'hir>>`,
|
||||
/// but it is implemented as 2 layers of arrays.
|
||||
/// - first we have `A = IndexVec<DefIndex, B>` mapping `DefIndex`s to an inner value
|
||||
@ -162,11 +138,8 @@ pub(super) type HirEntryMap<'hir> = IndexVec<DefIndex, IndexVec<ItemLocalId, Opt
|
||||
/// Represents a mapping from `NodeId`s to AST elements and their parent `NodeId`s.
|
||||
#[derive(Clone)]
|
||||
pub struct Map<'hir> {
|
||||
/// The backing storage for all the AST nodes.
|
||||
pub forest: &'hir Forest<'hir>,
|
||||
krate: &'hir Crate<'hir>,
|
||||
|
||||
/// Same as the dep_graph in forest, just available with one fewer
|
||||
/// deref. This is a gratuitous micro-optimization.
|
||||
pub dep_graph: DepGraph,
|
||||
|
||||
/// The SVH of the local crate.
|
||||
@ -217,6 +190,13 @@ impl<'hir> Iterator for ParentHirIterator<'_, 'hir> {
|
||||
}
|
||||
|
||||
impl<'hir> Map<'hir> {
|
||||
/// This is used internally in the dependency tracking system.
|
||||
/// Use the `krate` method to ensure your dependency on the
|
||||
/// crate is tracked.
|
||||
pub fn untracked_krate(&self) -> &Crate<'hir> {
|
||||
&self.krate
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn lookup(&self, id: HirId) -> Option<&Entry<'hir>> {
|
||||
let local_map = self.map.get(id.owner)?;
|
||||
@ -401,40 +381,36 @@ impl<'hir> Map<'hir> {
|
||||
self.lookup(id).cloned()
|
||||
}
|
||||
|
||||
pub fn krate(&self) -> &'hir Crate<'hir> {
|
||||
self.forest.krate()
|
||||
}
|
||||
|
||||
pub fn item(&self, id: HirId) -> &'hir Item<'hir> {
|
||||
self.read(id);
|
||||
|
||||
// N.B., intentionally bypass `self.forest.krate()` so that we
|
||||
// N.B., intentionally bypass `self.krate()` so that we
|
||||
// do not trigger a read of the whole krate here
|
||||
self.forest.krate.item(id)
|
||||
self.krate.item(id)
|
||||
}
|
||||
|
||||
pub fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir> {
|
||||
self.read(id.hir_id);
|
||||
|
||||
// N.B., intentionally bypass `self.forest.krate()` so that we
|
||||
// N.B., intentionally bypass `self.krate()` so that we
|
||||
// do not trigger a read of the whole krate here
|
||||
self.forest.krate.trait_item(id)
|
||||
self.krate.trait_item(id)
|
||||
}
|
||||
|
||||
pub fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> {
|
||||
self.read(id.hir_id);
|
||||
|
||||
// N.B., intentionally bypass `self.forest.krate()` so that we
|
||||
// N.B., intentionally bypass `self.krate()` so that we
|
||||
// do not trigger a read of the whole krate here
|
||||
self.forest.krate.impl_item(id)
|
||||
self.krate.impl_item(id)
|
||||
}
|
||||
|
||||
pub fn body(&self, id: BodyId) -> &'hir Body<'hir> {
|
||||
self.read(id.hir_id);
|
||||
|
||||
// N.B., intentionally bypass `self.forest.krate()` so that we
|
||||
// N.B., intentionally bypass `self.krate()` so that we
|
||||
// do not trigger a read of the whole krate here
|
||||
self.forest.krate.body(id)
|
||||
self.krate.body(id)
|
||||
}
|
||||
|
||||
pub fn fn_decl_by_hir_id(&self, hir_id: HirId) -> Option<&'hir FnDecl<'hir>> {
|
||||
@ -530,9 +506,9 @@ impl<'hir> Map<'hir> {
|
||||
pub fn trait_impls(&self, trait_did: DefId) -> &'hir [HirId] {
|
||||
self.dep_graph.read(DepNode::new_no_params(DepKind::AllLocalTraitImpls));
|
||||
|
||||
// N.B., intentionally bypass `self.forest.krate()` so that we
|
||||
// N.B., intentionally bypass `self.krate()` so that we
|
||||
// do not trigger a read of the whole krate here
|
||||
self.forest.krate.trait_impls.get(&trait_did).map_or(&[], |xs| &xs[..])
|
||||
self.krate.trait_impls.get(&trait_did).map_or(&[], |xs| &xs[..])
|
||||
}
|
||||
|
||||
/// Gets the attributes on the crate. This is preferable to
|
||||
@ -542,7 +518,7 @@ impl<'hir> Map<'hir> {
|
||||
let def_path_hash = self.definitions.def_path_hash(CRATE_DEF_INDEX);
|
||||
|
||||
self.dep_graph.read(def_path_hash.to_dep_node(DepKind::Hir));
|
||||
&self.forest.krate.attrs
|
||||
&self.krate.attrs
|
||||
}
|
||||
|
||||
pub fn get_module(&self, module: DefId) -> (&'hir Mod<'hir>, Span, HirId) {
|
||||
@ -550,7 +526,7 @@ impl<'hir> Map<'hir> {
|
||||
self.read(hir_id);
|
||||
match self.find_entry(hir_id).unwrap().node {
|
||||
Node::Item(&Item { span, kind: ItemKind::Mod(ref m), .. }) => (m, span, hir_id),
|
||||
Node::Crate => (&self.forest.krate.module, self.forest.krate.span, hir_id),
|
||||
Node::Crate => (&self.krate.module, self.krate.span, hir_id),
|
||||
node => panic!("not a module: {:?}", node),
|
||||
}
|
||||
}
|
||||
@ -567,7 +543,7 @@ impl<'hir> Map<'hir> {
|
||||
// in the expect_* calls the loops below
|
||||
self.read(hir_id);
|
||||
|
||||
let module = &self.forest.krate.modules[&hir_id];
|
||||
let module = &self.krate.modules[&hir_id];
|
||||
|
||||
for id in &module.items {
|
||||
visitor.visit_item(self.expect_item(*id));
|
||||
@ -984,7 +960,7 @@ impl<'hir> Map<'hir> {
|
||||
// Unit/tuple structs/variants take the attributes straight from
|
||||
// the struct/variant definition.
|
||||
Some(Node::Ctor(..)) => return self.attrs(self.get_parent_item(id)),
|
||||
Some(Node::Crate) => Some(&self.forest.krate.attrs[..]),
|
||||
Some(Node::Crate) => Some(&self.krate.attrs[..]),
|
||||
_ => None,
|
||||
};
|
||||
attrs.unwrap_or(&[])
|
||||
@ -1063,7 +1039,7 @@ impl<'hir> Map<'hir> {
|
||||
Some(Node::Visibility(v)) => bug!("unexpected Visibility {:?}", v),
|
||||
Some(Node::Local(local)) => local.span,
|
||||
Some(Node::MacroDef(macro_def)) => macro_def.span,
|
||||
Some(Node::Crate) => self.forest.krate.span,
|
||||
Some(Node::Crate) => self.krate.span,
|
||||
None => bug!("hir::map::Map::span: id not in map: {:?}", hir_id),
|
||||
}
|
||||
}
|
||||
@ -1231,7 +1207,8 @@ impl Named for ImplItem<'_> {
|
||||
pub fn map_crate<'hir>(
|
||||
sess: &rustc_session::Session,
|
||||
cstore: &CrateStoreDyn,
|
||||
forest: &'hir Forest<'hir>,
|
||||
krate: &'hir Crate<'hir>,
|
||||
dep_graph: DepGraph,
|
||||
definitions: Definitions,
|
||||
) -> Map<'hir> {
|
||||
let _prof_timer = sess.prof.generic_activity("build_hir_map");
|
||||
@ -1244,31 +1221,18 @@ pub fn map_crate<'hir>(
|
||||
.collect();
|
||||
|
||||
let (map, crate_hash) = {
|
||||
let hcx = crate::ich::StableHashingContext::new(sess, &forest.krate, &definitions, cstore);
|
||||
let hcx = crate::ich::StableHashingContext::new(sess, krate, &definitions, cstore);
|
||||
|
||||
let mut collector = NodeCollector::root(
|
||||
sess,
|
||||
&forest.krate,
|
||||
&forest.dep_graph,
|
||||
&definitions,
|
||||
&hir_to_node_id,
|
||||
hcx,
|
||||
);
|
||||
intravisit::walk_crate(&mut collector, &forest.krate);
|
||||
let mut collector =
|
||||
NodeCollector::root(sess, krate, &dep_graph, &definitions, &hir_to_node_id, hcx);
|
||||
intravisit::walk_crate(&mut collector, krate);
|
||||
|
||||
let crate_disambiguator = sess.local_crate_disambiguator();
|
||||
let cmdline_args = sess.opts.dep_tracking_hash();
|
||||
collector.finalize_and_compute_crate_hash(crate_disambiguator, cstore, cmdline_args)
|
||||
};
|
||||
|
||||
let map = Map {
|
||||
forest,
|
||||
dep_graph: forest.dep_graph.clone(),
|
||||
crate_hash,
|
||||
map,
|
||||
hir_to_node_id,
|
||||
definitions,
|
||||
};
|
||||
let map = Map { krate, dep_graph, crate_hash, map, hir_to_node_id, definitions };
|
||||
|
||||
sess.time("validate_HIR_map", || {
|
||||
hir_id_validator::check_crate(&map);
|
||||
|
@ -7,7 +7,48 @@ pub mod exports;
|
||||
pub mod map;
|
||||
|
||||
use crate::ty::query::Providers;
|
||||
use crate::ty::TyCtxt;
|
||||
use rustc_hir::def_id::LOCAL_CRATE;
|
||||
use rustc_hir::print;
|
||||
use rustc_hir::Crate;
|
||||
use std::ops::Deref;
|
||||
|
||||
/// A wrapper type which allows you to access HIR.
|
||||
#[derive(Clone)]
|
||||
pub struct Hir<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
map: &'tcx map::Map<'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx> Hir<'tcx> {
|
||||
pub fn krate(&self) -> &'tcx Crate<'tcx> {
|
||||
self.tcx.hir_crate(LOCAL_CRATE)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Deref for Hir<'tcx> {
|
||||
type Target = &'tcx map::Map<'tcx>;
|
||||
|
||||
#[inline(always)]
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.map
|
||||
}
|
||||
}
|
||||
|
||||
impl<'hir> print::PpAnn for Hir<'hir> {
|
||||
fn nested(&self, state: &mut print::State<'_>, nested: print::Nested) {
|
||||
self.map.nested(state, nested)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TyCtxt<'tcx> {
|
||||
#[inline(always)]
|
||||
pub fn hir(self) -> Hir<'tcx> {
|
||||
Hir { tcx: self, map: &self.hir_map }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn provide(providers: &mut Providers<'_>) {
|
||||
providers.hir_crate = |tcx, _| tcx.hir_map.untracked_krate();
|
||||
map::provide(providers);
|
||||
}
|
||||
|
@ -12,13 +12,6 @@ use smallvec::SmallVec;
|
||||
|
||||
impl<'ctx> rustc_target::HashStableContext for StableHashingContext<'ctx> {}
|
||||
|
||||
impl<'a> HashStable<StableHashingContext<'a>> for ast::Lifetime {
|
||||
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
|
||||
self.id.hash_stable(hcx, hasher);
|
||||
self.ident.hash_stable(hcx, hasher);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> HashStable<StableHashingContext<'a>> for [ast::Attribute] {
|
||||
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
|
||||
if self.len() == 0 {
|
||||
|
@ -72,6 +72,14 @@ bitflags! {
|
||||
const FFI_RETURNS_TWICE = 1 << 10;
|
||||
/// `#[track_caller]`: allow access to the caller location
|
||||
const TRACK_CALLER = 1 << 11;
|
||||
/// `#[no_sanitize(address)]`: disables address sanitizer instrumentation
|
||||
const NO_SANITIZE_ADDRESS = 1 << 12;
|
||||
/// `#[no_sanitize(memory)]`: disables memory sanitizer instrumentation
|
||||
const NO_SANITIZE_MEMORY = 1 << 13;
|
||||
/// `#[no_sanitize(thread)]`: disables thread sanitizer instrumentation
|
||||
const NO_SANITIZE_THREAD = 1 << 14;
|
||||
/// All `#[no_sanitize(...)]` attributes.
|
||||
const NO_SANITIZE_ANY = Self::NO_SANITIZE_ADDRESS.bits | Self::NO_SANITIZE_MEMORY.bits | Self::NO_SANITIZE_THREAD.bits;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,18 @@ rustc_queries! {
|
||||
}
|
||||
|
||||
Other {
|
||||
// Represents crate as a whole (as distinct from the top-level crate module).
|
||||
// If you call `hir_crate` (e.g., indirectly by calling `tcx.hir().krate()`),
|
||||
// we will have to assume that any change means that you need to be recompiled.
|
||||
// This is because the `hir_crate` query gives you access to all other items.
|
||||
// To avoid this fate, do not call `tcx.hir().krate()`; instead,
|
||||
// prefer wrappers like `tcx.visit_all_items_in_krate()`.
|
||||
query hir_crate(key: CrateNum) -> &'tcx Crate<'tcx> {
|
||||
eval_always
|
||||
no_hash
|
||||
desc { "get the crate HIR" }
|
||||
}
|
||||
|
||||
/// Records the type of every item.
|
||||
query type_of(key: DefId) -> Ty<'tcx> {
|
||||
cache_on_disk_if { key.is_local() }
|
||||
|
@ -966,7 +966,8 @@ pub struct GlobalCtxt<'tcx> {
|
||||
/// Export map produced by name resolution.
|
||||
export_map: FxHashMap<DefId, Vec<Export<hir::HirId>>>,
|
||||
|
||||
hir_map: hir_map::Map<'tcx>,
|
||||
/// This should usually be accessed with the `tcx.hir()` method.
|
||||
pub(crate) hir_map: hir_map::Map<'tcx>,
|
||||
|
||||
/// A map from `DefPathHash` -> `DefId`. Includes `DefId`s from the local crate
|
||||
/// as well as all upstream crates. Only populated in incremental mode.
|
||||
@ -1019,11 +1020,6 @@ pub struct GlobalCtxt<'tcx> {
|
||||
}
|
||||
|
||||
impl<'tcx> TyCtxt<'tcx> {
|
||||
#[inline(always)]
|
||||
pub fn hir(self) -> &'tcx hir_map::Map<'tcx> {
|
||||
&self.hir_map
|
||||
}
|
||||
|
||||
pub fn alloc_steal_mir(self, mir: BodyAndCache<'tcx>) -> &'tcx Steal<BodyAndCache<'tcx>> {
|
||||
self.arena.alloc(Steal::new(mir))
|
||||
}
|
||||
@ -1328,7 +1324,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
|
||||
#[inline(always)]
|
||||
pub fn create_stable_hashing_context(self) -> StableHashingContext<'tcx> {
|
||||
let krate = self.gcx.hir_map.forest.untracked_krate();
|
||||
let krate = self.gcx.hir_map.untracked_krate();
|
||||
|
||||
StableHashingContext::new(self.sess, krate, self.hir().definitions(), &*self.cstore)
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ use rustc_data_structures::sync::Lrc;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, DefIndex};
|
||||
use rustc_hir::{HirIdSet, ItemLocalId, TraitCandidate};
|
||||
use rustc_hir::{Crate, HirIdSet, ItemLocalId, TraitCandidate};
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_target::spec::PanicStrategy;
|
||||
|
||||
|
@ -1177,7 +1177,6 @@ pub fn force_from_dep_node(tcx: TyCtxt<'_>, dep_node: &DepNode) -> bool {
|
||||
// These are inputs that are expected to be pre-allocated and that
|
||||
// should therefore always be red or green already.
|
||||
DepKind::AllLocalTraitImpls |
|
||||
DepKind::Krate |
|
||||
DepKind::CrateMetadata |
|
||||
DepKind::HirBody |
|
||||
DepKind::Hir |
|
||||
|
@ -46,6 +46,31 @@ fn inline(cx: &CodegenCx<'ll, '_>, val: &'ll Value, inline: InlineAttr) {
|
||||
};
|
||||
}
|
||||
|
||||
/// Apply LLVM sanitize attributes.
|
||||
#[inline]
|
||||
pub fn sanitize(cx: &CodegenCx<'ll, '_>, codegen_fn_flags: CodegenFnAttrFlags, llfn: &'ll Value) {
|
||||
if let Some(ref sanitizer) = cx.tcx.sess.opts.debugging_opts.sanitizer {
|
||||
match *sanitizer {
|
||||
Sanitizer::Address => {
|
||||
if !codegen_fn_flags.contains(CodegenFnAttrFlags::NO_SANITIZE_ADDRESS) {
|
||||
llvm::Attribute::SanitizeAddress.apply_llfn(Function, llfn);
|
||||
}
|
||||
}
|
||||
Sanitizer::Memory => {
|
||||
if !codegen_fn_flags.contains(CodegenFnAttrFlags::NO_SANITIZE_MEMORY) {
|
||||
llvm::Attribute::SanitizeMemory.apply_llfn(Function, llfn);
|
||||
}
|
||||
}
|
||||
Sanitizer::Thread => {
|
||||
if !codegen_fn_flags.contains(CodegenFnAttrFlags::NO_SANITIZE_THREAD) {
|
||||
llvm::Attribute::SanitizeThread.apply_llfn(Function, llfn);
|
||||
}
|
||||
}
|
||||
Sanitizer::Leak => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Tell LLVM to emit or not emit the information necessary to unwind the stack for the function.
|
||||
#[inline]
|
||||
pub fn emit_uwtable(val: &'ll Value, emit: bool) {
|
||||
@ -288,6 +313,7 @@ pub fn from_fn_attrs(
|
||||
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::ALLOCATOR) {
|
||||
Attribute::NoAlias.apply_llfn(llvm::AttributePlace::ReturnValue, llfn);
|
||||
}
|
||||
sanitize(cx, codegen_fn_attrs.flags, llfn);
|
||||
|
||||
unwind(
|
||||
llfn,
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
use super::ModuleLlvm;
|
||||
|
||||
use crate::attributes;
|
||||
use crate::builder::Builder;
|
||||
use crate::common;
|
||||
use crate::context::CodegenCx;
|
||||
@ -23,7 +24,7 @@ use crate::metadata;
|
||||
use crate::value::Value;
|
||||
|
||||
use rustc::dep_graph;
|
||||
use rustc::middle::codegen_fn_attrs::CodegenFnAttrs;
|
||||
use rustc::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
|
||||
use rustc::middle::cstore::EncodedMetadata;
|
||||
use rustc::middle::exported_symbols;
|
||||
use rustc::mir::mono::{Linkage, Visibility};
|
||||
@ -131,7 +132,9 @@ pub fn compile_codegen_unit(
|
||||
|
||||
// If this codegen unit contains the main function, also create the
|
||||
// wrapper here
|
||||
maybe_create_entry_wrapper::<Builder<'_, '_, '_>>(&cx);
|
||||
if let Some(entry) = maybe_create_entry_wrapper::<Builder<'_, '_, '_>>(&cx) {
|
||||
attributes::sanitize(&cx, CodegenFnAttrFlags::empty(), entry);
|
||||
}
|
||||
|
||||
// Run replace-all-uses-with for statics that need it
|
||||
for &(old_g, new_g) in cx.statics_to_rauw().borrow().iter() {
|
||||
|
@ -19,7 +19,6 @@ use crate::llvm::AttributePlace::Function;
|
||||
use crate::type_::Type;
|
||||
use crate::value::Value;
|
||||
use log::debug;
|
||||
use rustc::session::config::Sanitizer;
|
||||
use rustc::ty::Ty;
|
||||
use rustc_codegen_ssa::traits::*;
|
||||
use rustc_data_structures::small_c_str::SmallCStr;
|
||||
@ -47,21 +46,6 @@ fn declare_raw_fn(
|
||||
llvm::Attribute::NoRedZone.apply_llfn(Function, llfn);
|
||||
}
|
||||
|
||||
if let Some(ref sanitizer) = cx.tcx.sess.opts.debugging_opts.sanitizer {
|
||||
match *sanitizer {
|
||||
Sanitizer::Address => {
|
||||
llvm::Attribute::SanitizeAddress.apply_llfn(Function, llfn);
|
||||
}
|
||||
Sanitizer::Memory => {
|
||||
llvm::Attribute::SanitizeMemory.apply_llfn(Function, llfn);
|
||||
}
|
||||
Sanitizer::Thread => {
|
||||
llvm::Attribute::SanitizeThread.apply_llfn(Function, llfn);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
attributes::default_optimisation_attrs(cx.tcx.sess, llfn);
|
||||
attributes::non_lazy_bind(cx.sess(), llfn);
|
||||
llfn
|
||||
|
@ -391,10 +391,12 @@ pub fn codegen_instance<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
|
||||
/// Creates the `main` function which will initialize the rust runtime and call
|
||||
/// users main function.
|
||||
pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(cx: &'a Bx::CodegenCx) {
|
||||
pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
cx: &'a Bx::CodegenCx,
|
||||
) -> Option<Bx::Function> {
|
||||
let (main_def_id, span) = match cx.tcx().entry_fn(LOCAL_CRATE) {
|
||||
Some((def_id, _)) => (def_id, cx.tcx().def_span(def_id)),
|
||||
None => return,
|
||||
None => return None,
|
||||
};
|
||||
|
||||
let instance = Instance::mono(cx.tcx(), main_def_id);
|
||||
@ -402,17 +404,15 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(cx: &'
|
||||
if !cx.codegen_unit().contains_item(&MonoItem::Fn(instance)) {
|
||||
// We want to create the wrapper in the same codegen unit as Rust's main
|
||||
// function.
|
||||
return;
|
||||
return None;
|
||||
}
|
||||
|
||||
let main_llfn = cx.get_fn_addr(instance);
|
||||
|
||||
let et = cx.tcx().entry_fn(LOCAL_CRATE).map(|e| e.1);
|
||||
match et {
|
||||
Some(EntryFnType::Main) => create_entry_fn::<Bx>(cx, span, main_llfn, main_def_id, true),
|
||||
Some(EntryFnType::Start) => create_entry_fn::<Bx>(cx, span, main_llfn, main_def_id, false),
|
||||
None => {} // Do nothing.
|
||||
}
|
||||
return cx.tcx().entry_fn(LOCAL_CRATE).map(|(_, et)| {
|
||||
let use_start_lang_item = EntryFnType::Start != et;
|
||||
create_entry_fn::<Bx>(cx, span, main_llfn, main_def_id, use_start_lang_item)
|
||||
});
|
||||
|
||||
fn create_entry_fn<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
cx: &'a Bx::CodegenCx,
|
||||
@ -420,7 +420,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(cx: &'
|
||||
rust_main: Bx::Value,
|
||||
rust_main_def_id: DefId,
|
||||
use_start_lang_item: bool,
|
||||
) {
|
||||
) -> Bx::Function {
|
||||
// The entry function is either `int main(void)` or `int main(int argc, char **argv)`,
|
||||
// depending on whether the target needs `argc` and `argv` to be passed in.
|
||||
let llfty = if cx.sess().target.target.options.main_needs_argc_argv {
|
||||
@ -481,6 +481,8 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(cx: &'
|
||||
let result = bx.call(start_fn, &args, None);
|
||||
let cast = bx.intcast(result, cx.type_int(), true);
|
||||
bx.ret(cast);
|
||||
|
||||
llfn
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,19 +69,19 @@ where
|
||||
match *ppmode {
|
||||
PpmNormal => {
|
||||
let annotation = NoAnn { sess: tcx.sess, tcx: Some(tcx) };
|
||||
f(&annotation, tcx.hir().forest.krate())
|
||||
f(&annotation, tcx.hir().krate())
|
||||
}
|
||||
|
||||
PpmIdentified => {
|
||||
let annotation = IdentifiedAnnotation { sess: tcx.sess, tcx: Some(tcx) };
|
||||
f(&annotation, tcx.hir().forest.krate())
|
||||
f(&annotation, tcx.hir().krate())
|
||||
}
|
||||
PpmTyped => {
|
||||
abort_on_err(tcx.analysis(LOCAL_CRATE), tcx.sess);
|
||||
|
||||
let empty_tables = ty::TypeckTables::empty(None);
|
||||
let annotation = TypedAnnotation { tcx, tables: Cell::new(&empty_tables) };
|
||||
tcx.dep_graph.with_ignore(|| f(&annotation, tcx.hir().forest.krate()))
|
||||
tcx.dep_graph.with_ignore(|| f(&annotation, tcx.hir().krate()))
|
||||
}
|
||||
_ => panic!("Should use call_with_pp_support"),
|
||||
}
|
||||
@ -143,7 +143,7 @@ impl<'hir> HirPrinterSupport<'hir> for NoAnn<'hir> {
|
||||
}
|
||||
|
||||
fn hir_map<'a>(&'a self) -> Option<&'a hir_map::Map<'hir>> {
|
||||
self.tcx.map(|tcx| tcx.hir())
|
||||
self.tcx.map(|tcx| *tcx.hir())
|
||||
}
|
||||
|
||||
fn pp_ann<'a>(&'a self) -> &'a dyn pprust_hir::PpAnn {
|
||||
@ -155,7 +155,7 @@ impl<'hir> pprust::PpAnn for NoAnn<'hir> {}
|
||||
impl<'hir> pprust_hir::PpAnn for NoAnn<'hir> {
|
||||
fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) {
|
||||
if let Some(tcx) = self.tcx {
|
||||
pprust_hir::PpAnn::nested(tcx.hir(), state, nested)
|
||||
pprust_hir::PpAnn::nested(*tcx.hir(), state, nested)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -217,7 +217,7 @@ impl<'hir> HirPrinterSupport<'hir> for IdentifiedAnnotation<'hir> {
|
||||
}
|
||||
|
||||
fn hir_map<'a>(&'a self) -> Option<&'a hir_map::Map<'hir>> {
|
||||
self.tcx.map(|tcx| tcx.hir())
|
||||
self.tcx.map(|tcx| *tcx.hir())
|
||||
}
|
||||
|
||||
fn pp_ann<'a>(&'a self) -> &'a dyn pprust_hir::PpAnn {
|
||||
@ -228,7 +228,7 @@ impl<'hir> HirPrinterSupport<'hir> for IdentifiedAnnotation<'hir> {
|
||||
impl<'hir> pprust_hir::PpAnn for IdentifiedAnnotation<'hir> {
|
||||
fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) {
|
||||
if let Some(ref tcx) = self.tcx {
|
||||
pprust_hir::PpAnn::nested(tcx.hir(), state, nested)
|
||||
pprust_hir::PpAnn::nested(*tcx.hir(), state, nested)
|
||||
}
|
||||
}
|
||||
fn pre(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) {
|
||||
@ -334,7 +334,7 @@ impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> {
|
||||
if let pprust_hir::Nested::Body(id) = nested {
|
||||
self.tables.set(self.tcx.body_tables(id));
|
||||
}
|
||||
pprust_hir::PpAnn::nested(self.tcx.hir(), state, nested);
|
||||
pprust_hir::PpAnn::nested(*self.tcx.hir(), state, nested);
|
||||
self.tables.set(old_tables);
|
||||
}
|
||||
fn pre(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) {
|
||||
|
@ -1,5 +1,6 @@
|
||||
This error occurs when a bound in an implementation of a trait does not match
|
||||
the bounds specified in the original trait. For example:
|
||||
A trait implementation has stricter requirements than the trait definition.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0276
|
||||
trait Foo {
|
||||
|
@ -541,6 +541,9 @@ declare_features! (
|
||||
/// Allows `T: ?const Trait` syntax in bounds.
|
||||
(active, const_trait_bound_opt_out, "1.42.0", Some(67794), None),
|
||||
|
||||
/// Allows the use of `no_sanitize` attribute.
|
||||
(active, no_sanitize, "1.42.0", Some(39699), None),
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// feature-group-end: actual feature gates
|
||||
// -------------------------------------------------------------------------
|
||||
|
@ -261,6 +261,11 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||
ungated!(cold, Whitelisted, template!(Word)),
|
||||
ungated!(no_builtins, Whitelisted, template!(Word)),
|
||||
ungated!(target_feature, Whitelisted, template!(List: r#"enable = "name""#)),
|
||||
gated!(
|
||||
no_sanitize, Whitelisted,
|
||||
template!(List: "address, memory, thread"),
|
||||
experimental!(no_sanitize)
|
||||
),
|
||||
|
||||
// FIXME: #14408 whitelist docs since rustdoc looks at them
|
||||
ungated!(doc, Whitelisted, template!(List: "hidden|inline|...", NameValueStr: "string")),
|
||||
|
@ -25,6 +25,7 @@ use rustc_data_structures::{box_region_allow_access, declare_box_region_type, pa
|
||||
use rustc_errors::PResult;
|
||||
use rustc_expand::base::ExtCtxt;
|
||||
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
|
||||
use rustc_hir::Crate;
|
||||
use rustc_lint::LintStore;
|
||||
use rustc_mir as mir;
|
||||
use rustc_mir_build as mir_build;
|
||||
@ -422,7 +423,7 @@ pub fn lower_to_hir<'res, 'tcx>(
|
||||
dep_graph: &'res DepGraph,
|
||||
krate: &'res ast::Crate,
|
||||
arena: &'tcx Arena<'tcx>,
|
||||
) -> Result<map::Forest<'tcx>> {
|
||||
) -> Crate<'tcx> {
|
||||
// Lower AST to HIR.
|
||||
let hir_crate = rustc_ast_lowering::lower_crate(
|
||||
sess,
|
||||
@ -437,8 +438,6 @@ pub fn lower_to_hir<'res, 'tcx>(
|
||||
hir_stats::print_hir_stats(&hir_crate);
|
||||
}
|
||||
|
||||
let hir_forest = map::Forest::new(hir_crate, &dep_graph);
|
||||
|
||||
sess.time("early_lint_checks", || {
|
||||
rustc_lint::check_ast_crate(
|
||||
sess,
|
||||
@ -455,7 +454,7 @@ pub fn lower_to_hir<'res, 'tcx>(
|
||||
rustc_span::hygiene::clear_syntax_context_map();
|
||||
}
|
||||
|
||||
Ok(hir_forest)
|
||||
hir_crate
|
||||
}
|
||||
|
||||
// Returns all the paths that correspond to generated files.
|
||||
@ -705,7 +704,8 @@ impl<'tcx> QueryContext<'tcx> {
|
||||
pub fn create_global_ctxt<'tcx>(
|
||||
compiler: &'tcx Compiler,
|
||||
lint_store: Lrc<LintStore>,
|
||||
hir_forest: &'tcx map::Forest<'tcx>,
|
||||
krate: &'tcx Crate<'tcx>,
|
||||
dep_graph: DepGraph,
|
||||
mut resolver_outputs: ResolverOutputs,
|
||||
outputs: OutputFilenames,
|
||||
crate_name: &str,
|
||||
@ -716,7 +716,7 @@ pub fn create_global_ctxt<'tcx>(
|
||||
let defs = mem::take(&mut resolver_outputs.definitions);
|
||||
|
||||
// Construct the HIR map.
|
||||
let hir_map = map::map_crate(sess, &*resolver_outputs.cstore, &hir_forest, defs);
|
||||
let hir_map = map::map_crate(sess, &*resolver_outputs.cstore, krate, dep_graph, defs);
|
||||
|
||||
let query_result_on_disk_cache = rustc_incremental::load_query_result_cache(sess);
|
||||
|
||||
|
@ -3,7 +3,6 @@ use crate::passes::{self, BoxedResolver, QueryContext};
|
||||
|
||||
use rustc::arena::Arena;
|
||||
use rustc::dep_graph::DepGraph;
|
||||
use rustc::hir::map;
|
||||
use rustc::session::config::{OutputFilenames, OutputType};
|
||||
use rustc::session::Session;
|
||||
use rustc::ty::steal::Steal;
|
||||
@ -12,6 +11,7 @@ use rustc::util::common::ErrorReported;
|
||||
use rustc_codegen_utils::codegen_backend::CodegenBackend;
|
||||
use rustc_data_structures::sync::{Lrc, Once, WorkerLocal};
|
||||
use rustc_hir::def_id::LOCAL_CRATE;
|
||||
use rustc_hir::Crate;
|
||||
use rustc_incremental::DepGraphFuture;
|
||||
use rustc_lint::LintStore;
|
||||
use std::any::Any;
|
||||
@ -74,7 +74,7 @@ pub struct Queries<'tcx> {
|
||||
register_plugins: Query<(ast::Crate, Lrc<LintStore>)>,
|
||||
expansion: Query<(ast::Crate, Steal<Rc<RefCell<BoxedResolver>>>, Lrc<LintStore>)>,
|
||||
dep_graph: Query<DepGraph>,
|
||||
lower_to_hir: Query<(&'tcx map::Forest<'tcx>, Steal<ResolverOutputs>)>,
|
||||
lower_to_hir: Query<(&'tcx Crate<'tcx>, Steal<ResolverOutputs>)>,
|
||||
prepare_outputs: Query<OutputFilenames>,
|
||||
global_ctxt: Query<QueryContext<'tcx>>,
|
||||
ongoing_codegen: Query<Box<dyn Any>>,
|
||||
@ -207,9 +207,7 @@ impl<'tcx> Queries<'tcx> {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn lower_to_hir(
|
||||
&'tcx self,
|
||||
) -> Result<&Query<(&'tcx map::Forest<'tcx>, Steal<ResolverOutputs>)>> {
|
||||
pub fn lower_to_hir(&'tcx self) -> Result<&Query<(&'tcx Crate<'tcx>, Steal<ResolverOutputs>)>> {
|
||||
self.lower_to_hir.compute(|| {
|
||||
let expansion_result = self.expansion()?;
|
||||
let peeked = expansion_result.peek();
|
||||
@ -217,14 +215,14 @@ impl<'tcx> Queries<'tcx> {
|
||||
let resolver = peeked.1.steal();
|
||||
let lint_store = &peeked.2;
|
||||
let hir = resolver.borrow_mut().access(|resolver| {
|
||||
passes::lower_to_hir(
|
||||
Ok(passes::lower_to_hir(
|
||||
self.session(),
|
||||
lint_store,
|
||||
resolver,
|
||||
&*self.dep_graph()?.peek(),
|
||||
&krate,
|
||||
&self.arena,
|
||||
)
|
||||
))
|
||||
})?;
|
||||
let hir = self.arena.alloc(hir);
|
||||
Ok((hir, Steal::new(BoxedResolver::to_resolver_outputs(resolver))))
|
||||
@ -253,12 +251,14 @@ impl<'tcx> Queries<'tcx> {
|
||||
let outputs = self.prepare_outputs()?.peek().clone();
|
||||
let lint_store = self.expansion()?.peek().2.clone();
|
||||
let hir = self.lower_to_hir()?.peek();
|
||||
let (ref hir_forest, ref resolver_outputs) = &*hir;
|
||||
let dep_graph = self.dep_graph()?.peek().clone();
|
||||
let (ref krate, ref resolver_outputs) = &*hir;
|
||||
let _timer = self.session().timer("create_global_ctxt");
|
||||
Ok(passes::create_global_ctxt(
|
||||
self.compiler,
|
||||
lint_store,
|
||||
hir_forest,
|
||||
krate,
|
||||
dep_graph,
|
||||
resolver_outputs.steal(),
|
||||
outputs,
|
||||
&crate_name,
|
||||
|
@ -796,7 +796,7 @@ impl EncodeContext<'tcx> {
|
||||
record!(self.per_def.kind[def_id] <- match trait_item.kind {
|
||||
ty::AssocKind::Const => {
|
||||
let rendered =
|
||||
hir::print::to_string(self.tcx.hir(), |s| s.print_trait_item(ast_item));
|
||||
hir::print::to_string(&self.tcx.hir(), |s| s.print_trait_item(ast_item));
|
||||
let rendered_const = self.lazy(RenderedConst(rendered));
|
||||
|
||||
EntryKind::AssocConst(
|
||||
@ -1009,7 +1009,7 @@ impl EncodeContext<'tcx> {
|
||||
|
||||
fn encode_rendered_const_for_body(&mut self, body_id: hir::BodyId) -> Lazy<RenderedConst> {
|
||||
let body = self.tcx.hir().body(body_id);
|
||||
let rendered = hir::print::to_string(self.tcx.hir(), |s| s.print_expr(&body.value));
|
||||
let rendered = hir::print::to_string(&self.tcx.hir(), |s| s.print_expr(&body.value));
|
||||
let rendered_const = &RenderedConst(rendered);
|
||||
self.lazy(rendered_const)
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ use rustc_index::vec::{Idx, IndexVec};
|
||||
use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||
use rustc::mir::visit::*;
|
||||
use rustc::mir::*;
|
||||
use rustc::session::config::Sanitizer;
|
||||
use rustc::ty::subst::{InternalSubsts, Subst, SubstsRef};
|
||||
use rustc::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt, TypeFoldable};
|
||||
|
||||
@ -228,6 +229,28 @@ impl Inliner<'tcx> {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Avoid inlining functions marked as no_sanitize if sanitizer is enabled,
|
||||
// since instrumentation might be enabled and performed on the caller.
|
||||
match self.tcx.sess.opts.debugging_opts.sanitizer {
|
||||
Some(Sanitizer::Address) => {
|
||||
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NO_SANITIZE_ADDRESS) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Some(Sanitizer::Memory) => {
|
||||
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NO_SANITIZE_MEMORY) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Some(Sanitizer::Thread) => {
|
||||
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NO_SANITIZE_THREAD) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Some(Sanitizer::Leak) => {}
|
||||
None => {}
|
||||
}
|
||||
|
||||
let hinted = match codegen_fn_attrs.inline {
|
||||
// Just treat inline(always) as a hint for now,
|
||||
// there are cases that prevent inlining that we
|
||||
|
@ -8,6 +8,7 @@
|
||||
//! through, but errors for structured control flow in a `const` should be emitted here.
|
||||
|
||||
use rustc::hir::map::Map;
|
||||
use rustc::hir::Hir;
|
||||
use rustc::session::config::nightly_options;
|
||||
use rustc::session::parse::feature_err;
|
||||
use rustc::ty::query::Providers;
|
||||
@ -74,7 +75,7 @@ enum ConstKind {
|
||||
}
|
||||
|
||||
impl ConstKind {
|
||||
fn for_body(body: &hir::Body<'_>, hir_map: &Map<'_>) -> Option<Self> {
|
||||
fn for_body(body: &hir::Body<'_>, hir_map: Hir<'_>) -> Option<Self> {
|
||||
let is_const_fn = |id| hir_map.fn_sig_by_hir_id(id).unwrap().header.is_const();
|
||||
|
||||
let owner = hir_map.body_owner(body.id());
|
||||
|
@ -1,4 +1,4 @@
|
||||
use rustc::hir::map as hir_map;
|
||||
use rustc::hir::Hir;
|
||||
use rustc::session::config::EntryFnType;
|
||||
use rustc::session::{config, Session};
|
||||
use rustc::ty::query::Providers;
|
||||
@ -15,7 +15,7 @@ use syntax::entry::EntryPointType;
|
||||
struct EntryContext<'a, 'tcx> {
|
||||
session: &'a Session,
|
||||
|
||||
map: &'a hir_map::Map<'tcx>,
|
||||
map: Hir<'tcx>,
|
||||
|
||||
/// The top-level function called `main`.
|
||||
main_fn: Option<(HirId, Span)>,
|
||||
|
@ -612,7 +612,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||
let parent_id = self.tcx.hir().get_parent_node(hir_id);
|
||||
let parent_impl_id = hir::ImplItemId { hir_id: parent_id };
|
||||
let parent_trait_id = hir::TraitItemId { hir_id: parent_id };
|
||||
let krate = self.tcx.hir().forest.krate();
|
||||
let krate = self.tcx.hir().krate();
|
||||
|
||||
if !(krate.items.contains_key(&parent_id)
|
||||
|| krate.impl_items.contains_key(&parent_impl_id)
|
||||
|
@ -474,6 +474,12 @@ declare_lint! {
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub INLINE_NO_SANITIZE,
|
||||
Warn,
|
||||
"detects incompatible use of `#[inline(always)]` and `#[no_sanitize(...)]`",
|
||||
}
|
||||
|
||||
declare_lint_pass! {
|
||||
/// Does nothing as a lint pass, but registers some `Lint`s
|
||||
/// that are used by other parts of the compiler.
|
||||
@ -537,5 +543,6 @@ declare_lint_pass! {
|
||||
MUTABLE_BORROW_RESERVATION_CONFLICT,
|
||||
INDIRECT_STRUCTURAL_MATCH,
|
||||
SOFT_UNSTABLE,
|
||||
INLINE_NO_SANITIZE,
|
||||
]
|
||||
}
|
||||
|
@ -120,6 +120,7 @@ symbols! {
|
||||
abi_vectorcall,
|
||||
abi_x86_interrupt,
|
||||
aborts,
|
||||
address,
|
||||
add_with_overflow,
|
||||
advanced_slice_patterns,
|
||||
adx_target_feature,
|
||||
@ -445,6 +446,7 @@ symbols! {
|
||||
mem_uninitialized,
|
||||
mem_zeroed,
|
||||
member_constraints,
|
||||
memory,
|
||||
message,
|
||||
meta,
|
||||
min_align_of,
|
||||
@ -487,6 +489,7 @@ symbols! {
|
||||
None,
|
||||
non_exhaustive,
|
||||
non_modrs_mods,
|
||||
no_sanitize,
|
||||
no_stack_check,
|
||||
no_start,
|
||||
no_std,
|
||||
@ -721,6 +724,7 @@ symbols! {
|
||||
test_removed_feature,
|
||||
test_runner,
|
||||
then_with,
|
||||
thread,
|
||||
thread_local,
|
||||
tool_attributes,
|
||||
tool_lints,
|
||||
|
@ -2598,7 +2598,7 @@ fn report_unexpected_variant_res(tcx: TyCtxt<'_>, res: Res, span: Span, qpath: &
|
||||
E0533,
|
||||
"expected unit struct, unit variant or constant, found {} `{}`",
|
||||
res.descr(),
|
||||
hir::print::to_string(tcx.hir(), |s| s.print_qpath(qpath, false))
|
||||
hir::print::to_string(&tcx.hir(), |s| s.print_qpath(qpath, false))
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
|
@ -693,7 +693,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let msg = format!(
|
||||
"expected tuple struct or tuple variant, found {} `{}`",
|
||||
res.descr(),
|
||||
hir::print::to_string(tcx.hir(), |s| s.print_qpath(qpath, false)),
|
||||
hir::print::to_string(&tcx.hir(), |s| s.print_qpath(qpath, false)),
|
||||
);
|
||||
let mut err = struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg);
|
||||
match (res, &pat.kind) {
|
||||
|
@ -1,3 +1,5 @@
|
||||
// ignore-tidy-filelength
|
||||
|
||||
//! "Collection" is the process of determining the type and other external
|
||||
//! details of each item in Rust. Collection is specifically concerned
|
||||
//! with *inter-procedural* things -- for example, for a function
|
||||
@ -2743,6 +2745,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
|
||||
|
||||
let mut inline_span = None;
|
||||
let mut link_ordinal_span = None;
|
||||
let mut no_sanitize_span = None;
|
||||
for attr in attrs.iter() {
|
||||
if attr.check_name(sym::cold) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD;
|
||||
@ -2832,6 +2835,24 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
|
||||
if let ordinal @ Some(_) = check_link_ordinal(tcx, attr) {
|
||||
codegen_fn_attrs.link_ordinal = ordinal;
|
||||
}
|
||||
} else if attr.check_name(sym::no_sanitize) {
|
||||
no_sanitize_span = Some(attr.span);
|
||||
if let Some(list) = attr.meta_item_list() {
|
||||
for item in list.iter() {
|
||||
if item.check_name(sym::address) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_SANITIZE_ADDRESS;
|
||||
} else if item.check_name(sym::memory) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_SANITIZE_MEMORY;
|
||||
} else if item.check_name(sym::thread) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_SANITIZE_THREAD;
|
||||
} else {
|
||||
tcx.sess
|
||||
.struct_span_err(item.span(), "invalid argument for `no_sanitize`")
|
||||
.note("expected one of: `address`, `memory` or `thread`")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2911,7 +2932,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
|
||||
// purpose functions as they wouldn't have the right target features
|
||||
// enabled. For that reason we also forbid #[inline(always)] as it can't be
|
||||
// respected.
|
||||
|
||||
if codegen_fn_attrs.target_features.len() > 0 {
|
||||
if codegen_fn_attrs.inline == InlineAttr::Always {
|
||||
if let Some(span) = inline_span {
|
||||
@ -2924,6 +2944,22 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
|
||||
}
|
||||
}
|
||||
|
||||
if codegen_fn_attrs.flags.intersects(CodegenFnAttrFlags::NO_SANITIZE_ANY) {
|
||||
if codegen_fn_attrs.inline == InlineAttr::Always {
|
||||
if let (Some(no_sanitize_span), Some(inline_span)) = (no_sanitize_span, inline_span) {
|
||||
let hir_id = tcx.hir().as_local_hir_id(id).unwrap();
|
||||
tcx.struct_span_lint_hir(
|
||||
lint::builtin::INLINE_NO_SANITIZE,
|
||||
hir_id,
|
||||
no_sanitize_span,
|
||||
"`no_sanitize` will have no effect after inlining",
|
||||
)
|
||||
.span_note(inline_span, "inlining requested here")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Weak lang items have the same semantics as "std internal" symbols in the
|
||||
// sense that they're preserved through all our LTO passes and only
|
||||
// strippable by the linker.
|
||||
|
@ -87,7 +87,7 @@ pub fn run(options: Options) -> i32 {
|
||||
compiler.enter(|queries| {
|
||||
let lower_to_hir = queries.lower_to_hir()?;
|
||||
|
||||
let mut opts = scrape_test_config(lower_to_hir.peek().0.krate());
|
||||
let mut opts = scrape_test_config(lower_to_hir.peek().0);
|
||||
opts.display_warnings |= options.display_warnings;
|
||||
let enable_per_target_ignores = options.enable_per_target_ignores;
|
||||
let mut collector = Collector::new(
|
||||
@ -107,7 +107,7 @@ pub fn run(options: Options) -> i32 {
|
||||
let mut hir_collector = HirCollector {
|
||||
sess: compiler.session(),
|
||||
collector: &mut collector,
|
||||
map: tcx.hir(),
|
||||
map: *tcx.hir(),
|
||||
codes: ErrorCodes::from(
|
||||
compiler.session().opts.unstable_features.is_nightly_build(),
|
||||
),
|
||||
|
@ -63,8 +63,7 @@ use std::{
|
||||
env, io,
|
||||
io::prelude::Write,
|
||||
panic::{self, catch_unwind, AssertUnwindSafe, PanicInfo},
|
||||
process,
|
||||
process::{Command, Termination},
|
||||
process::{self, Command, Termination},
|
||||
sync::mpsc::{channel, Sender},
|
||||
sync::{Arc, Mutex},
|
||||
thread,
|
||||
@ -457,9 +456,13 @@ pub fn run_test(
|
||||
monitor_ch,
|
||||
opts.time,
|
||||
),
|
||||
RunStrategy::SpawnPrimary => {
|
||||
spawn_test_subprocess(desc, opts.time.is_some(), monitor_ch, opts.time)
|
||||
}
|
||||
RunStrategy::SpawnPrimary => spawn_test_subprocess(
|
||||
desc,
|
||||
opts.nocapture,
|
||||
opts.time.is_some(),
|
||||
monitor_ch,
|
||||
opts.time,
|
||||
),
|
||||
};
|
||||
|
||||
// If the platform is single-threaded we're just going to run
|
||||
@ -558,6 +561,7 @@ fn run_test_in_process(
|
||||
|
||||
fn spawn_test_subprocess(
|
||||
desc: TestDesc,
|
||||
nocapture: bool,
|
||||
report_time: bool,
|
||||
monitor_ch: Sender<CompletedTest>,
|
||||
time_opts: Option<time::TestTimeOptions>,
|
||||
@ -566,11 +570,15 @@ fn spawn_test_subprocess(
|
||||
let args = env::args().collect::<Vec<_>>();
|
||||
let current_exe = &args[0];
|
||||
|
||||
let mut command = Command::new(current_exe);
|
||||
command.env(SECONDARY_TEST_INVOKER_VAR, desc.name.as_slice());
|
||||
if nocapture {
|
||||
command.stdout(process::Stdio::inherit());
|
||||
command.stderr(process::Stdio::inherit());
|
||||
}
|
||||
|
||||
let start = report_time.then(Instant::now);
|
||||
let output = match Command::new(current_exe)
|
||||
.env(SECONDARY_TEST_INVOKER_VAR, desc.name.as_slice())
|
||||
.output()
|
||||
{
|
||||
let output = match command.output() {
|
||||
Ok(out) => out,
|
||||
Err(e) => {
|
||||
let err = format!("Failed to spawn {} as child for test: {:?}", args[0], e);
|
||||
|
32
src/test/codegen/sanitizer-no-sanitize-inlining.rs
Normal file
32
src/test/codegen/sanitizer-no-sanitize-inlining.rs
Normal file
@ -0,0 +1,32 @@
|
||||
// Verifies that no_sanitize attribute prevents inlining when
|
||||
// given sanitizer is enabled, but has no effect on inlining otherwise.
|
||||
//
|
||||
// needs-sanitizer-support
|
||||
// only-x86_64
|
||||
//
|
||||
// revisions: ASAN LSAN
|
||||
//
|
||||
//[ASAN] compile-flags: -Zsanitizer=address -C opt-level=3 -Z mir-opt-level=3
|
||||
//[LSAN] compile-flags: -Zsanitizer=leak -C opt-level=3 -Z mir-opt-level=3
|
||||
|
||||
#![crate_type="lib"]
|
||||
#![feature(no_sanitize)]
|
||||
|
||||
// ASAN-LABEL: define void @test
|
||||
// ASAN: tail call fastcc void @random_inline
|
||||
// ASAN: }
|
||||
//
|
||||
// LSAN-LABEL: define void @test
|
||||
// LSAN-NO: call
|
||||
// LSAN: }
|
||||
#[no_mangle]
|
||||
pub fn test(n: &mut u32) {
|
||||
random_inline(n);
|
||||
}
|
||||
|
||||
#[no_sanitize(address)]
|
||||
#[inline]
|
||||
#[no_mangle]
|
||||
pub fn random_inline(n: &mut u32) {
|
||||
*n = 42;
|
||||
}
|
29
src/test/codegen/sanitizer-no-sanitize.rs
Normal file
29
src/test/codegen/sanitizer-no-sanitize.rs
Normal file
@ -0,0 +1,29 @@
|
||||
// Verifies that no_sanitze attribute can be used to
|
||||
// selectively disable sanitizer instrumentation.
|
||||
//
|
||||
// needs-sanitizer-support
|
||||
// compile-flags: -Zsanitizer=address
|
||||
|
||||
#![crate_type="lib"]
|
||||
#![feature(no_sanitize)]
|
||||
|
||||
// CHECK-LABEL: ; sanitizer_no_sanitize::unsanitized
|
||||
// CHECK-NEXT: ; Function Attrs:
|
||||
// CHECK-NOT: sanitize_address
|
||||
// CHECK: start:
|
||||
// CHECK-NOT: call void @__asan_report_load
|
||||
// CHECK: }
|
||||
#[no_sanitize(address)]
|
||||
pub fn unsanitized(b: &mut u8) -> u8 {
|
||||
*b
|
||||
}
|
||||
|
||||
// CHECK-LABEL: ; sanitizer_no_sanitize::sanitized
|
||||
// CHECK-NEXT: ; Function Attrs:
|
||||
// CHECK: sanitize_address
|
||||
// CHECK: start:
|
||||
// CHECK: call void @__asan_report_load
|
||||
// CHECK: }
|
||||
pub fn sanitized(b: &mut u8) -> u8 {
|
||||
*b
|
||||
}
|
@ -7,11 +7,9 @@
|
||||
|
||||
// Check that reordering otherwise identical items is not considered a
|
||||
// change at all.
|
||||
#[rustc_clean(label="Krate", cfg="rpass2")]
|
||||
|
||||
#[rustc_clean(label = "hir_crate", cfg = "rpass2")]
|
||||
// But removing an item, naturally, is.
|
||||
#[rustc_dirty(label="Krate", cfg="rpass3")]
|
||||
|
||||
#[rustc_dirty(label = "hir_crate", cfg = "rpass3")]
|
||||
#[cfg(rpass1)]
|
||||
pub struct X {
|
||||
pub x: u32,
|
||||
@ -26,4 +24,4 @@ pub struct X {
|
||||
pub x: u32,
|
||||
}
|
||||
|
||||
pub fn main() { }
|
||||
pub fn main() {}
|
||||
|
@ -1,18 +1,14 @@
|
||||
// Test that debuginfo does not introduce a dependency edge to the Krate
|
||||
// Test that debuginfo does not introduce a dependency edge to the hir_crate
|
||||
// dep-node.
|
||||
|
||||
// revisions:rpass1 rpass2
|
||||
// compile-flags: -Z query-dep-graph
|
||||
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
|
||||
#![rustc_partition_reused(module="issue_38222-mod1", cfg="rpass2")]
|
||||
|
||||
// If codegen had added a dependency edge to the Krate dep-node, nothing would
|
||||
#![rustc_partition_reused(module = "issue_38222-mod1", cfg = "rpass2")]
|
||||
// If codegen had added a dependency edge to the hir_crate dep-node, nothing would
|
||||
// be re-used, so checking that this module was re-used is sufficient.
|
||||
#![rustc_partition_reused(module="issue_38222", cfg="rpass2")]
|
||||
#![rustc_partition_reused(module = "issue_38222", cfg = "rpass2")]
|
||||
|
||||
//[rpass1] compile-flags: -C debuginfo=1
|
||||
//[rpass2] compile-flags: -C debuginfo=1
|
||||
|
@ -4,20 +4,20 @@
|
||||
|
||||
#![allow(warnings)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![rustc_partition_reused(module="krate_inherent-x", cfg="cfail2")]
|
||||
#![rustc_partition_reused(module = "krate_inherent-x", cfg = "cfail2")]
|
||||
#![crate_type = "rlib"]
|
||||
|
||||
pub mod x {
|
||||
pub struct Foo;
|
||||
impl Foo {
|
||||
pub fn foo(&self) { }
|
||||
pub fn foo(&self) {}
|
||||
}
|
||||
|
||||
pub fn method() {
|
||||
let x: Foo = Foo;
|
||||
x.foo(); // inherent methods used to add an edge from Krate
|
||||
x.foo(); // inherent methods used to add an edge from hir_crate
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(cfail1)]
|
||||
pub fn bar() { } // remove this unrelated fn in cfail2, which should not affect `x::method`
|
||||
pub fn bar() {} // remove this unrelated fn in cfail2, which should not affect `x::method`
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Regr. test that using HIR inlined from another krate does *not* add
|
||||
// a dependency from the local Krate node. We can't easily test that
|
||||
// a dependency from the local hir_crate node. We can't easily test that
|
||||
// directly anymore, so now we test that we get reuse.
|
||||
|
||||
// revisions: rpass1 rpass2
|
||||
@ -7,7 +7,7 @@
|
||||
|
||||
#![allow(warnings)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![rustc_partition_reused(module="krate_inlined-x", cfg="rpass2")]
|
||||
#![rustc_partition_reused(module = "krate_inlined-x", cfg = "rpass2")]
|
||||
|
||||
fn main() {
|
||||
x::method();
|
||||
|
@ -6,17 +6,16 @@
|
||||
#![feature(rustc_attrs)]
|
||||
#![allow(dead_code)]
|
||||
#![allow(unused_variables)]
|
||||
|
||||
fn main() { }
|
||||
#![rustc_if_this_changed(hir_crate)]
|
||||
fn main() {}
|
||||
|
||||
struct Foo<T> {
|
||||
f: T
|
||||
f: T,
|
||||
}
|
||||
|
||||
#[rustc_if_this_changed(Krate)]
|
||||
type TypeAlias<T> = Foo<T>;
|
||||
|
||||
#[rustc_then_this_would_need(variances_of)] //~ ERROR OK
|
||||
struct Use<T> {
|
||||
x: TypeAlias<T>
|
||||
x: TypeAlias<T>,
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: OK
|
||||
--> $DIR/dep-graph-variance-alias.rs:19:1
|
||||
--> $DIR/dep-graph-variance-alias.rs:18:1
|
||||
|
|
||||
LL | #[rustc_then_this_would_need(variances_of)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
4
src/test/ui/feature-gates/feature-gate-no_sanitize.rs
Normal file
4
src/test/ui/feature-gates/feature-gate-no_sanitize.rs
Normal file
@ -0,0 +1,4 @@
|
||||
#[no_sanitize(address)]
|
||||
//~^ the `#[no_sanitize]` attribute is an experimental feature
|
||||
fn main() {
|
||||
}
|
12
src/test/ui/feature-gates/feature-gate-no_sanitize.stderr
Normal file
12
src/test/ui/feature-gates/feature-gate-no_sanitize.stderr
Normal file
@ -0,0 +1,12 @@
|
||||
error[E0658]: the `#[no_sanitize]` attribute is an experimental feature
|
||||
--> $DIR/feature-gate-no_sanitize.rs:1:1
|
||||
|
|
||||
LL | #[no_sanitize(address)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/39699
|
||||
= help: add `#![feature(no_sanitize)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
5
src/test/ui/invalid/invalid-no-sanitize.rs
Normal file
5
src/test/ui/invalid/invalid-no-sanitize.rs
Normal file
@ -0,0 +1,5 @@
|
||||
#![feature(no_sanitize)]
|
||||
|
||||
#[no_sanitize(brontosaurus)] //~ ERROR invalid argument
|
||||
fn main() {
|
||||
}
|
10
src/test/ui/invalid/invalid-no-sanitize.stderr
Normal file
10
src/test/ui/invalid/invalid-no-sanitize.stderr
Normal file
@ -0,0 +1,10 @@
|
||||
error: invalid argument for `no_sanitize`
|
||||
--> $DIR/invalid-no-sanitize.rs:3:15
|
||||
|
|
||||
LL | #[no_sanitize(brontosaurus)]
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected one of: `address`, `memory` or `thread`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
15
src/test/ui/sanitize-inline-always.rs
Normal file
15
src/test/ui/sanitize-inline-always.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// check-pass
|
||||
|
||||
#![feature(no_sanitize)]
|
||||
|
||||
#[inline(always)]
|
||||
//~^ NOTE inlining requested here
|
||||
#[no_sanitize(address)]
|
||||
//~^ WARN will have no effect after inlining
|
||||
//~| NOTE on by default
|
||||
fn x() {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
x()
|
||||
}
|
13
src/test/ui/sanitize-inline-always.stderr
Normal file
13
src/test/ui/sanitize-inline-always.stderr
Normal file
@ -0,0 +1,13 @@
|
||||
warning: `no_sanitize` will have no effect after inlining
|
||||
--> $DIR/sanitize-inline-always.rs:7:1
|
||||
|
|
||||
LL | #[no_sanitize(address)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(inline_no_sanitize)]` on by default
|
||||
note: inlining requested here
|
||||
--> $DIR/sanitize-inline-always.rs:5:1
|
||||
|
|
||||
LL | #[inline(always)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
39
src/test/ui/test-panic-abort-nocapture.rs
Normal file
39
src/test/ui/test-panic-abort-nocapture.rs
Normal file
@ -0,0 +1,39 @@
|
||||
// no-prefer-dynamic
|
||||
// compile-flags: --test -Cpanic=abort -Zpanic_abort_tests
|
||||
// run-flags: --test-threads=1 --nocapture
|
||||
// run-fail
|
||||
// check-run-results
|
||||
// exec-env:RUST_BACKTRACE=0
|
||||
|
||||
// ignore-wasm no panic or subprocess support
|
||||
// ignore-emscripten no panic or subprocess support
|
||||
|
||||
#![cfg(test)]
|
||||
|
||||
use std::io::Write;
|
||||
|
||||
#[test]
|
||||
fn it_works() {
|
||||
println!("about to succeed");
|
||||
assert_eq!(1 + 1, 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn it_panics() {
|
||||
println!("about to panic");
|
||||
assert_eq!(1 + 1, 4);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_fails() {
|
||||
println!("about to fail");
|
||||
assert_eq!(1 + 1, 4);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_writes_to_stdio() {
|
||||
println!("hello, world");
|
||||
writeln!(std::io::stdout(), "testing123").unwrap();
|
||||
writeln!(std::io::stderr(), "testing321").unwrap();
|
||||
}
|
9
src/test/ui/test-panic-abort-nocapture.run.stderr
Normal file
9
src/test/ui/test-panic-abort-nocapture.run.stderr
Normal file
@ -0,0 +1,9 @@
|
||||
thread 'main' panicked at 'assertion failed: `(left == right)`
|
||||
left: `2`,
|
||||
right: `4`', $DIR/test-panic-abort-nocapture.rs:31:5
|
||||
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
|
||||
thread 'main' panicked at 'assertion failed: `(left == right)`
|
||||
left: `2`,
|
||||
right: `4`', $DIR/test-panic-abort-nocapture.rs:25:5
|
||||
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
|
||||
testing321
|
23
src/test/ui/test-panic-abort-nocapture.run.stdout
Normal file
23
src/test/ui/test-panic-abort-nocapture.run.stdout
Normal file
@ -0,0 +1,23 @@
|
||||
|
||||
running 4 tests
|
||||
test it_fails ... about to fail
|
||||
FAILED
|
||||
test it_panics ... about to panic
|
||||
ok
|
||||
test it_works ... about to succeed
|
||||
ok
|
||||
test it_writes_to_stdio ... hello, world
|
||||
testing123
|
||||
ok
|
||||
|
||||
failures:
|
||||
|
||||
---- it_fails stdout ----
|
||||
---- it_fails stderr ----
|
||||
|
||||
|
||||
failures:
|
||||
it_fails
|
||||
|
||||
test result: FAILED. 3 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out
|
||||
|
Loading…
Reference in New Issue
Block a user