Skip to content

Commit 1bd3bb8

Browse files
authored
Merge 1a47bab into d5fc73f
2 parents d5fc73f + 1a47bab commit 1bd3bb8

File tree

12 files changed

+635
-744
lines changed

12 files changed

+635
-744
lines changed

source/compiler/qsc/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub use qsc_frontend::compile::{CompileUnit, PackageStore, SourceContents, Sourc
1515

1616
pub mod resolve {
1717
pub use qsc_frontend::resolve::{
18-
Local, LocalKind, Locals, Res, iter_valid_items, path_as_field_accessor,
18+
GlobalScope, Local, Locals, NameKind, Res, iter_valid_items, path_as_field_accessor,
1919
};
2020
}
2121

source/compiler/qsc_frontend/src/compile.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ pub mod preprocess;
99
use crate::{
1010
error::WithSource,
1111
lower::{self, Lowerer},
12-
resolve::{self, Locals, Names, Resolver},
12+
resolve::{self, GlobalScope, Locals, Names, Resolver},
1313
typeck::{self, Checker, Table},
1414
};
1515

@@ -62,6 +62,7 @@ pub struct AstPackage {
6262
pub tys: Table,
6363
pub names: Names,
6464
pub locals: Locals,
65+
pub globals: GlobalScope,
6566
}
6667

6768
#[derive(Clone, Debug, Default)]
@@ -397,6 +398,7 @@ pub fn compile_ast(
397398
let ResolveResult {
398399
names,
399400
locals,
401+
globals,
400402
errors: name_errors,
401403
} = resolve_all(
402404
store,
@@ -429,6 +431,7 @@ pub fn compile_ast(
429431
tys,
430432
names,
431433
locals,
434+
globals,
432435
},
433436
assigner: hir_assigner,
434437
sources,
@@ -550,6 +553,7 @@ pub fn get_target_profile_from_entry_point(
550553
pub(crate) struct ResolveResult {
551554
pub names: Names,
552555
pub locals: Locals,
556+
pub globals: GlobalScope,
553557
pub errors: Vec<resolve::Error>,
554558
}
555559

@@ -581,13 +585,14 @@ fn resolve_all(
581585

582586
// resolve all symbols, binding imports/export names as they're resolved
583587
resolver.resolve(assigner, package);
584-
let (names, _, locals, mut resolver_errors) = resolver.into_result();
588+
let (names, globals, locals, mut resolver_errors) = resolver.into_result();
585589

586590
errors.append(&mut resolver_errors);
587591

588592
ResolveResult {
589593
names,
590594
locals,
595+
globals,
591596
errors,
592597
}
593598
}

source/compiler/qsc_frontend/src/incremental.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ impl Compiler {
190190
package: ast,
191191
names: self.resolver.names().clone(),
192192
locals: self.resolver.locals().clone(),
193+
globals: self.resolver.globals().clone(),
193194
tys: self.checker.table().clone(),
194195
},
195196
hir,
@@ -229,6 +230,7 @@ impl Compiler {
229230
package: ast,
230231
names: self.resolver.names().clone(),
231232
locals: self.resolver.locals().clone(),
233+
globals: self.resolver.globals().clone(),
232234
tys: self.checker.table().clone(),
233235
},
234236
hir,
@@ -245,6 +247,7 @@ impl Compiler {
245247
unit.ast.names = new.ast.names;
246248
unit.ast.tys = new.ast.tys;
247249
unit.ast.locals = new.ast.locals;
250+
unit.ast.globals = new.ast.globals;
248251

249252
// Update the HIR
250253
extend_hir(&mut unit.package, new.hir);

source/compiler/qsc_frontend/src/resolve.rs

Lines changed: 61 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ impl Locals {
341341

342342
// deduping by name will effectively make locals in a child scope
343343
// shadow the locals in its parent scopes
344-
all_locals.dedup_by(|a, b| a.name == b.name);
344+
all_locals.dedup_by(|a, b| a.name().is_some() && a.name() == b.name());
345345

346346
all_locals
347347
}
@@ -361,22 +361,28 @@ impl Locals {
361361
}
362362

363363
#[derive(Debug)]
364-
pub struct Local {
365-
pub name: Rc<str>,
366-
pub kind: LocalKind,
367-
}
368-
369-
#[derive(Debug)]
370-
pub enum LocalKind {
364+
pub enum Local {
371365
/// A local callable or UDT.
372-
Item(ItemId),
366+
Item(ItemId, Rc<str>),
373367
/// A type parameter.
374-
TyParam(ParamId),
368+
TyParam(ParamId, Rc<str>),
375369
/// A local variable or parameter.
376-
Var(NodeId),
370+
Var(NodeId, Rc<str>),
371+
/// A namespace import (`import Foo as A` or `open Foo`)
372+
NamespaceImport(NamespaceId, Option<Rc<str>>),
377373
}
378374

379-
#[derive(Debug, Default)]
375+
impl Local {
376+
#[must_use]
377+
pub fn name(&self) -> Option<&Rc<str>> {
378+
match self {
379+
Local::Item(_, name) | Local::TyParam(_, name) | Local::Var(_, name) => Some(name),
380+
Local::NamespaceImport(_, alias) => alias.as_ref(),
381+
}
382+
}
383+
}
384+
385+
#[derive(Debug, Default, Clone)]
380386
pub struct GlobalScope {
381387
/// Global names that are valid in a type context (UDTs, builtin types...)
382388
tys: IndexMap<NamespaceId, FxHashMap<Rc<str>, Res>>,
@@ -394,12 +400,17 @@ pub struct GlobalScope {
394400

395401
impl GlobalScope {
396402
fn get(&self, kind: NameKind, namespace: NamespaceId, name: &str) -> Option<&Res> {
397-
let items = match kind {
403+
self.table(kind)
404+
.get(namespace)
405+
.and_then(|items| items.get(name))
406+
}
407+
408+
pub fn table(&self, kind: NameKind) -> &IndexMap<NamespaceId, FxHashMap<Rc<str>, Res>> {
409+
match kind {
398410
NameKind::Term => &self.terms,
399411
NameKind::Ty => &self.tys,
400412
NameKind::Importable => &self.importables,
401-
};
402-
items.get(namespace).and_then(|items| items.get(name))
413+
}
403414
}
404415

405416
/// Creates a namespace in the namespace mapping. Note that namespaces are tracked separately from their
@@ -419,7 +430,7 @@ impl GlobalScope {
419430
}
420431

421432
/// Finds a namespace by its path.
422-
fn find_namespace<'a>(
433+
pub fn find_namespace<'a>(
423434
&self,
424435
name: impl IntoIterator<Item = &'a str>,
425436
root: Option<NamespaceId>,
@@ -459,12 +470,23 @@ impl GlobalScope {
459470
}
460471

461472
/// Returns the full namespace path for a given namespace ID.
462-
fn format_namespace_name(&self, namespace_id: NamespaceId) -> String {
473+
pub fn format_namespace_name(&self, namespace_id: NamespaceId) -> String {
463474
self.namespaces
464475
.find_namespace_by_id(&namespace_id)
465476
.0
466477
.join(".")
467478
}
479+
480+
pub fn namespace_children(&self, namespace_id: NamespaceId) -> Vec<Rc<str>> {
481+
self.namespaces
482+
.find_namespace_by_id(&namespace_id)
483+
.1
484+
.borrow()
485+
.children
486+
.keys()
487+
.cloned()
488+
.collect()
489+
}
468490
}
469491

470492
#[derive(Debug, Clone, Eq, PartialEq)]
@@ -475,7 +497,7 @@ enum ScopeKind {
475497
}
476498

477499
#[derive(Clone, Copy, Debug)]
478-
enum NameKind {
500+
pub enum NameKind {
479501
/// A name that is valid as an expression context: a callable or UDT
480502
Term,
481503
/// A name that is valid in a type context: builtin or UDT
@@ -590,6 +612,10 @@ impl Resolver {
590612
&self.locals
591613
}
592614

615+
pub(super) fn globals(&self) -> &GlobalScope {
616+
&self.globals
617+
}
618+
593619
pub(super) fn drain_errors(&mut self) -> vec::Drain<Error> {
594620
self.errors.drain(..)
595621
}
@@ -1271,6 +1297,11 @@ impl GlobalTable {
12711297
}
12721298
}
12731299
(global::Kind::Namespace(item_id), hir::Visibility::Public) => {
1300+
if package_root == Some(namespace) && global.name.as_ref() == "Main" {
1301+
// If the namespace is `Main` and we have an alias, we treat it as the root of the package,
1302+
// so there's no namespace prefix between the dependency alias and the defined items.
1303+
continue;
1304+
}
12741305
let this_namespace = self
12751306
.scope
12761307
.insert_or_find_namespace(vec![global.name.clone()], Some(namespace));
@@ -2014,10 +2045,7 @@ fn get_scope_locals(scope: &Scope, offset: u32, vars: bool) -> Vec<Local> {
20142045
// when a variable is later shadowed in the same scope,
20152046
// it is missed in the list. https://github.com/microsoft/qsharp/issues/897
20162047
if offset >= *valid_at {
2017-
Some(Local {
2018-
name: name.clone(),
2019-
kind: LocalKind::Var(*id),
2020-
})
2048+
Some(Local::Var(*id, name.clone()))
20212049
} else {
20222050
None
20232051
}
@@ -2027,26 +2055,28 @@ fn get_scope_locals(scope: &Scope, offset: u32, vars: bool) -> Vec<Local> {
20272055
scope
20282056
.ty_vars
20292057
.iter()
2030-
.map(|(name, (id, _constraints))| Local {
2031-
name: name.clone(),
2032-
kind: LocalKind::TyParam(*id),
2033-
}),
2058+
.map(|(name, (id, _constraints))| Local::TyParam(*id, name.clone())),
20342059
);
20352060
}
20362061

20372062
// items
2038-
// skip adding newtypes since they're already in the terms map
2063+
// gather from the terms table, since it happens to contain all the
2064+
// declared and imported callables and newtypes
20392065
names.extend(scope.terms.iter().filter_map(|(name, res)| {
20402066
if let Res::Item(id, _) = res {
2041-
Some(Local {
2042-
name: name.clone(),
2043-
kind: LocalKind::Item(*id),
2044-
})
2067+
Some(Local::Item(*id, name.clone()))
20452068
} else {
20462069
None
20472070
}
20482071
}));
20492072

2073+
// opens and namespace imports
2074+
names.extend(scope.opens.iter().flat_map(|(alias, opens)| {
2075+
opens
2076+
.iter()
2077+
.map(|open| Local::NamespaceImport(open.namespace, alias.clone()))
2078+
}));
2079+
20502080
names
20512081
}
20522082

0 commit comments

Comments
 (0)